1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2013 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDisplacementMapEffect.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXformer.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImageFilterPriv.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSpecialImage.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWriteBuffer.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUnPreMultiply.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorData.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrClip.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrColorSpaceXform.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrCoordTransform.h"
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrRenderTargetContext.h"
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTexture.h"
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureProxy.h"
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h"
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "effects/GrTextureDomain.h"
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentProcessor.h"
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentShaderBuilder.h"
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLProgramDataManager.h"
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLUniformHandler.h"
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace {
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst uint8_t gChannelTypeToShift[] = {
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     0,  // unknown
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_R32_SHIFT,
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_G32_SHIFT,
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_B32_SHIFT,
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_A32_SHIFT,
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Extractor {
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Extractor(SkDisplacementMapEffect::ChannelSelectorType typeX,
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot              SkDisplacementMapEffect::ChannelSelectorType typeY)
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fShiftX(gChannelTypeToShift[typeX])
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fShiftY(gChannelTypeToShift[typeY])
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {}
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned fShiftX, fShiftY;
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned getX(SkPMColor c) const { return (c >> fShiftX) & 0xFF; }
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned getY(SkPMColor c) const { return (c >> fShiftY) & 0xFF; }
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkPMColor unpremul_pm(SkPMColor c) {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const U8CPU a = SkGetPackedA32(c);
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == a) {
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 0;
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (0xFF == a) {
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return c;
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const unsigned scale = SkUnPreMultiply::GetScale(a);
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkPackARGB32NoCheck(a,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedR32(c)),
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedG32(c)),
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               SkUnPreMultiply::ApplyScale(scale, SkGetPackedB32(c)));
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid computeDisplacement(Extractor ex, const SkVector& scale, SkBitmap* dst,
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         const SkBitmap& displ, const SkIPoint& offset,
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         const SkBitmap& src,
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         const SkIRect& bounds) {
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const SkScalar Inv8bit = SkScalarInvert(255);
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int srcW = src.width();
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int srcH = src.height();
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkVector scaleForColor = SkVector::Make(scale.fX * Inv8bit, scale.fY * Inv8bit);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - scale.fX * SK_ScalarHalf,
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             SK_ScalarHalf - scale.fY * SK_ScalarHalf);
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPMColor* dstPtr = dst->getAddr32(0, 0);
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int y = bounds.top(); y < bounds.bottom(); ++y) {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPMColor* displPtr = displ.getAddr32(bounds.left() + offset.fX, y + offset.fY);
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) {
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPMColor c = unpremul_pm(*displPtr);
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar displX = scaleForColor.fX * ex.getX(c) + scaleAdj.fX;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar displY = scaleForColor.fY * ex.getY(c) + scaleAdj.fY;
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Truncate the displacement values
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int srcX = x + SkScalarTruncToInt(displX);
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int srcY = y + SkScalarTruncToInt(displY);
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ?
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      0 : *(src.getAddr32(srcX, srcY));
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) {
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (cst) {
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    case SkDisplacementMapEffect::kR_ChannelSelectorType:
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    case SkDisplacementMapEffect::kG_ChannelSelectorType:
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    case SkDisplacementMapEffect::kB_ChannelSelectorType:
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    case SkDisplacementMapEffect::kA_ChannelSelectorType:
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    default:
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} // end namespace
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkImageFilter> SkDisplacementMapEffect::Make(ChannelSelectorType xChannelSelector,
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   ChannelSelectorType yChannelSelector,
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   SkScalar scale,
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   sk_sp<SkImageFilter> displacement,
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   sk_sp<SkImageFilter> color,
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   const CropRect* cropRect) {
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!channel_selector_type_is_valid(xChannelSelector) ||
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        !channel_selector_type_is_valid(yChannelSelector)) {
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImageFilter> inputs[2] = { std::move(displacement), std::move(color) };
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_sp<SkImageFilter>(new SkDisplacementMapEffect(xChannelSelector,
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                            yChannelSelector,
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                            scale, inputs, cropRect));
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                 ChannelSelectorType yChannelSelector,
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                 SkScalar scale,
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                 sk_sp<SkImageFilter> inputs[2],
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                 const CropRect* cropRect)
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    : INHERITED(inputs, 2, cropRect)
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    , fXChannelSelector(xChannelSelector)
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    , fYChannelSelector(yChannelSelector)
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    , fScale(scale) {
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkDisplacementMapEffect::~SkDisplacementMapEffect() {
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkFlattenable> SkDisplacementMapEffect::CreateProc(SkReadBuffer& buffer) {
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ChannelSelectorType xsel = buffer.read32LE(kLast_ChannelSelectorType);
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ChannelSelectorType ysel = buffer.read32LE(kLast_ChannelSelectorType);
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar scale = buffer.readScalar();
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return Make(xsel, ysel, scale, common.getInput(0), common.getInput(1), &common.cropRect());
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->INHERITED::flatten(buffer);
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeInt((int) fXChannelSelector);
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeInt((int) fYChannelSelector);
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    buffer.writeScalar(fScale);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrDisplacementMapEffect : public GrFragmentProcessor {
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static std::unique_ptr<GrFragmentProcessor> Make(
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale,
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<GrTextureProxy> displacement, const SkMatrix& offsetMatrix,
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<GrTextureProxy> color, const SkISize& colorDimensions) {
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return std::unique_ptr<GrFragmentProcessor>(new GrDisplacementMapEffect(
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                xChannelSelector, yChannelSelector, scale, std::move(displacement), offsetMatrix,
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::move(color), colorDimensions));
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~GrDisplacementMapEffect() override;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const {
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fXChannelSelector;
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const {
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fYChannelSelector;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkVector& scale() const { return fScale; }
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return "DisplacementMap"; }
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrTextureDomain& domain() const { return fDomain; }
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<GrFragmentProcessor> clone() const override;
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static OptimizationFlags OptimizationFlags(GrPixelConfig colorConfig);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrDisplacementMapEffect(const GrDisplacementMapEffect&);
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onIsEqual(const GrFragmentProcessor&) const override;
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            const SkVector& scale,
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            sk_sp<GrTextureProxy> displacement, const SkMatrix& offsetMatrix,
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            sk_sp<GrTextureProxy> color, const SkISize& colorDimensions);
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrCoordTransform            fDisplacementTransform;
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureSampler              fDisplacementSampler;
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrCoordTransform            fColorTransform;
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTextureDomain             fDomain;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureSampler              fColorSampler;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkVector fScale;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrFragmentProcessor INHERITED;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* source,
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                             const Context& ctx,
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                             SkIPoint* offset) const {
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIPoint colorOffset = SkIPoint::Make(0, 0);
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkSpecialImage> color(this->filterInput(1, source, ctx, &colorOffset));
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!color) {
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIPoint displOffset = SkIPoint::Make(0, 0);
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Creation of the displacement map should happen in a non-colorspace aware context. This
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // texture is a purely mathematical construct, so we want to just operate on the stored
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // values. Consider:
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // User supplies an sRGB displacement map. If we're rendering to a wider gamut, then we could
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // end up filtering the displacement map into that gamut, which has the effect of reducing
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the amount of displacement that it represents (as encoded values move away from the
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // primaries).
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // With a more complex DAG attached to this input, it's not clear that working in ANY specific
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // color space makes sense, so we ignore color spaces (and gamma) entirely. This may not be
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // ideal, but it's at least consistent and predictable.
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Context displContext(ctx.ctm(), ctx.clipBounds(), ctx.cache(), OutputProperties(nullptr));
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkSpecialImage> displ(this->filterInput(0, source, displContext, &displOffset));
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!displ) {
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkIRect srcBounds = SkIRect::MakeXYWH(colorOffset.x(), colorOffset.y(),
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                color->width(), color->height());
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Both paths do bounds checking on color pixel access, we don't need to
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // pad the color bitmap to bounds here.
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIRect bounds;
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIRect displBounds;
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    displ = this->applyCropRect(ctx, displ.get(), &displOffset, &displBounds);
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!displ) {
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!bounds.intersect(displBounds)) {
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkIRect colorBounds = bounds.makeOffset(-colorOffset.x(), -colorOffset.y());
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkVector scale = SkVector::Make(fScale, fScale);
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ctx.ctm().mapVectors(&scale, 1);
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (source->isTextureBacked()) {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrContext* context = source->getContext();
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> colorProxy(color->asTextureProxyRef(context));
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> displProxy(displ->asTextureProxyRef(context));
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!colorProxy || !displProxy) {
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return nullptr;
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix offsetMatrix = SkMatrix::MakeTrans(SkIntToScalar(colorOffset.fX - displOffset.fX),
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    SkIntToScalar(colorOffset.fY - displOffset.fY));
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkColorSpace* colorSpace = ctx.outputProperties().colorSpace();
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPixelConfig colorConfig = colorProxy->config();
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::unique_ptr<GrFragmentProcessor> fp =
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                GrDisplacementMapEffect::Make(fXChannelSelector,
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              fYChannelSelector,
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              scale,
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              std::move(displProxy),
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              offsetMatrix,
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              std::move(colorProxy),
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              SkISize::Make(color->width(), color->height()));
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fp = GrColorSpaceXformEffect::Make(std::move(fp), color->getColorSpace(), colorConfig,
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           colorSpace);
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPaint paint;
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.addColorFragmentProcessor(std::move(fp));
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix matrix;
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrRenderTargetContext> renderTargetContext(
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            context->makeDeferredRenderTargetContext(SkBackingFit::kApprox,
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     bounds.width(), bounds.height(),
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     GrRenderableConfigForColorSpace(colorSpace),
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     sk_ref_sp(colorSpace)));
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!renderTargetContext) {
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return nullptr;
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setGammaCorrect(renderTargetContext->colorSpaceInfo().isGammaCorrect());
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      SkRect::Make(colorBounds));
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        offset->fX = bounds.left();
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        offset->fY = bounds.top();
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkSpecialImage::MakeDeferredFromGpu(
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                context,
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkIRect::MakeWH(bounds.width(), bounds.height()),
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kNeedNewImageUniqueID_SpecialImage,
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                renderTargetContext->asTextureProxyRef(),
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                renderTargetContext->colorSpaceInfo().refColorSpace());
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap colorBM, displBM;
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!color->getROPixels(&colorBM) || !displ->getROPixels(&displBM)) {
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ((colorBM.colorType() != kN32_SkColorType) ||
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        (displBM.colorType() != kN32_SkColorType)) {
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!colorBM.getPixels() || !displBM.getPixels()) {
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            colorBM.alphaType());
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap dst;
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!dst.tryAllocPixels(info)) {
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    computeDisplacement(Extractor(fXChannelSelector, fYChannelSelector), scale, &dst,
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        displBM, colorOffset - displOffset, colorBM, colorBounds);
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    offset->fX = bounds.left();
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    offset->fY = bounds.top();
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          dst);
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkImageFilter> SkDisplacementMapEffect::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(2 == this->countInputs());
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Intentionally avoid xforming the displacement filter.  The values will be used as
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // offsets, not as colors.
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImageFilter> displacement = sk_ref_sp(const_cast<SkImageFilter*>(this->getInput(0)));
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImageFilter> color = xformer->apply(this->getInput(1));
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (color.get() != this->getInput(1)) {
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkDisplacementMapEffect::Make(fXChannelSelector, fYChannelSelector, fScale,
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             std::move(displacement), std::move(color),
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             this->getCropRectIfSet());
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->refMe();
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkRect SkDisplacementMapEffect::computeFastBounds(const SkRect& src) const {
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect bounds = this->getColorInput() ? this->getColorInput()->computeFastBounds(src) : src;
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bounds.outset(SkScalarAbs(fScale) * SK_ScalarHalf, SkScalarAbs(fScale) * SK_ScalarHalf);
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return bounds;
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkIRect SkDisplacementMapEffect::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    MapDirection) const {
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkVector scale = SkVector::Make(fScale, fScale);
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ctm.mapVectors(&scale, 1);
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return src.makeOutset(SkScalarCeilToInt(SkScalarAbs(scale.fX) * SK_ScalarHalf),
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          SkScalarCeilToInt(SkScalarAbs(scale.fY) * SK_ScalarHalf));
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkIRect SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                MapDirection direction) const {
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Recurse only into color input.
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this->getColorInput()) {
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return this->getColorInput()->filterBounds(src, ctm, direction);
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return src;
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDisplacementMapEffect::toString(SkString* str) const {
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->appendf("SkDisplacementMapEffect: (");
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->appendf("scale: %f ", fScale);
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->appendf("displacement: (");
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this->getDisplacementInput()) {
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->getDisplacementInput()->toString(str);
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->appendf(") color: (");
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this->getColorInput()) {
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->getColorInput()->toString(str);
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    str->appendf("))");
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrGLDisplacementMapEffect : public GrGLSLFragmentProcessor {
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void emitCode(EmitArgs&) override;
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniformHandle fScaleUni;
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTextureDomain::GLDomain fGLDomain;
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrGLSLFragmentProcessor INHERITED;
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLSLFragmentProcessor* GrDisplacementMapEffect::onCreateGLSLInstance() const {
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return new GrGLDisplacementMapEffect;
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrDisplacementMapEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                    GrProcessorKeyBuilder* b) const {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLDisplacementMapEffect::GenKey(*this, caps, b);
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrFragmentProcessor::OptimizationFlags GrDisplacementMapEffect::OptimizationFlags(
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPixelConfig colorConfig) {
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrPixelConfigIsOpaque(colorConfig)
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   ? GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   : GrFragmentProcessor::kNone_OptimizationFlags;
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrDisplacementMapEffect::GrDisplacementMapEffect(
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkVector& scale,
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> displacement,
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkMatrix& offsetMatrix,
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> color,
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkISize& colorDimensions)
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(kGrDisplacementMapEffect_ClassID, OptimizationFlags(color->config()))
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDisplacementTransform(offsetMatrix, displacement.get())
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDisplacementSampler(displacement)
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fColorTransform(color.get())
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDomain(color.get(), GrTextureDomain::MakeTexelDomain(SkIRect::MakeSize(colorDimensions)),
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  GrTextureDomain::kDecal_Mode)
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fColorSampler(color)
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fXChannelSelector(xChannelSelector)
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fYChannelSelector(yChannelSelector)
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fScale(scale) {
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addCoordTransform(&fDisplacementTransform);
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addTextureSampler(&fDisplacementSampler);
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addCoordTransform(&fColorTransform);
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addTextureSampler(&fColorSampler);
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrDisplacementMapEffect::GrDisplacementMapEffect(const GrDisplacementMapEffect& that)
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : INHERITED(kGrDisplacementMapEffect_ClassID,
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    OptimizationFlags(that.fColorSampler.proxy()->config()))
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDisplacementTransform(that.fDisplacementTransform)
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDisplacementSampler(that.fDisplacementSampler)
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fColorTransform(that.fColorTransform)
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDomain(that.fDomain)
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fColorSampler(that.fColorSampler)
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fXChannelSelector(that.fXChannelSelector)
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fYChannelSelector(that.fYChannelSelector)
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fScale(that.fScale) {
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addCoordTransform(&fDisplacementTransform);
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addTextureSampler(&fDisplacementSampler);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addCoordTransform(&fColorTransform);
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->addTextureSampler(&fColorSampler);
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrDisplacementMapEffect::~GrDisplacementMapEffect() {}
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::clone() const {
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return std::unique_ptr<GrFragmentProcessor>(new GrDisplacementMapEffect(*this));
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fXChannelSelector == s.fXChannelSelector &&
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot           fYChannelSelector == s.fYChannelSelector &&
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot           fScale == s.fScale;
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if GR_TEST_UTILS
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) {
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               GrProcessorUnitTest::kAlphaTextureIdx;
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               GrProcessorUnitTest::kAlphaTextureIdx;
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrTextureProxy> dispProxy = d->textureProxy(texIdxDispl);
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrTextureProxy> colorProxy = d->textureProxy(texIdxColor);
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kMaxComponent = 4;
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                d->fRandom->nextRangeU(1, kMaxComponent));
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                d->fRandom->nextRangeU(1, kMaxComponent));
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkVector scale = SkVector::Make(d->fRandom->nextRangeScalar(0, 100.0f),
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    d->fRandom->nextRangeScalar(0, 100.0f));
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize colorDimensions;
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    colorDimensions.fWidth = d->fRandom->nextRangeU(0, colorProxy->width());
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    colorDimensions.fHeight = d->fRandom->nextRangeU(0, colorProxy->height());
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         std::move(dispProxy), SkMatrix::I(),
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         std::move(colorProxy), colorDimensions);
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrTextureDomain& domain = displacementMap.domain();
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "Scale");
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* dColor = "dColor";
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* cCoords = "cCoords";
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nearZero = "1e-6"; // Since 6.10352e-5 is the smallest half float, use
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   // a number smaller than that to approximate 0, but
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   // leave room for 32-bit float GPU rounding errors.
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   args.fTransformedCoords[0].getType());
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppend(";\n");
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Unpremultiply the displacement
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf(
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dColor, dColor, nearZero, dColor, dColor);
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             cCoords, coords2D.c_str(), scaleUni, dColor);
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (displacementMap.xChannelSelector()) {
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kR_ChannelSelectorType:
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("r");
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kG_ChannelSelectorType:
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("g");
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kB_ChannelSelectorType:
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("b");
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kA_ChannelSelectorType:
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("a");
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      default:
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGFAIL("Unknown X channel selector");
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (displacementMap.yChannelSelector()) {
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kR_ChannelSelectorType:
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("r");
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kG_ChannelSelectorType:
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("g");
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kB_ChannelSelectorType:
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("b");
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kA_ChannelSelectorType:
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fragBuilder->codeAppend("a");
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        break;
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot      default:
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGFAIL("Unknown Y channel selector");
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppend("-half2(0.5));\t\t");
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fGLDomain.sampleTexture(fragBuilder,
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fUniformHandler,
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fShaderCaps,
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            domain,
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fOutputColor,
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkString(cCoords),
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            args.fTexSamplers[1]);
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fragBuilder->codeAppend(";\n");
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman,
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                          const GrFragmentProcessor& proc) {
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrSurfaceProxy* proxy = displacementMap.textureSampler(1).proxy();
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTexture* colorTex = proxy->priv().peekTexture();
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar scaleX = displacementMap.scale().fX / colorTex->width();
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar scaleY = displacementMap.scale().fY / colorTex->height();
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                proxy->origin() == kTopLeft_GrSurfaceOrigin ?
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fGLDomain.setData(pdman, displacementMap.domain(), proxy);
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       const GrShaderCaps&, GrProcessorKeyBuilder* b) {
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint32_t xKey = displacementMap.xChannelSelector();
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    b->add32(xKey | yKey);
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
641