105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org/*
205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org * Copyright 2012 The Android Open Source Project
305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org *
405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org * found in the LICENSE file.
605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org */
705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org#include "SkMorphologyImageFilter.h"
964a0ec36555352ec31aa7c5a7630a5d042b010badjsollen@google.com#include "SkBitmap.h"
1005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org#include "SkColorPriv.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
13c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com#include "SkRect.h"
147a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "SkMorphology_opts.h"
15cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
16302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org#include "GrContext.h"
17302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org#include "GrTexture.h"
18b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h"
19b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
2030ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
2184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org#include "effects/Gr1DKernelEffect.h"
22cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
2305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
258b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkMorphologyImageFilter::SkMorphologyImageFilter(SkReadBuffer& buffer)
26ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  : INHERITED(1, buffer) {
2775589257c6ac7fc55a66502b74b8bc09c0212featomhudson@google.com    fRadius.fWidth = buffer.readInt();
2875589257c6ac7fc55a66502b74b8bc09c0212featomhudson@google.com    fRadius.fHeight = buffer.readInt();
29c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    buffer.validate((fRadius.fWidth >= 0) &&
30c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                    (fRadius.fHeight >= 0));
3105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
3305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
342bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.orgSkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX,
352bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org                                                 int radiusY,
362bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org                                                 SkImageFilter* input,
375e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                                 const CropRect* cropRect,
385e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                                 uint32_t uniqueID)
395e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    : INHERITED(1, &input, cropRect, uniqueID), fRadius(SkISize::Make(radiusX, radiusY)) {
4005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
4105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
428b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const {
4305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
4475589257c6ac7fc55a66502b74b8bc09c0212featomhudson@google.com    buffer.writeInt(fRadius.fWidth);
4575589257c6ac7fc55a66502b74b8bc09c0212featomhudson@google.com    buffer.writeInt(fRadius.fHeight);
4605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
4705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
487a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgenum MorphDirection {
497a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    kX, kY
507a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org};
517a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
527a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgtemplate<MorphDirection direction>
5305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.orgstatic void erode(const SkPMColor* src, SkPMColor* dst,
5405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                  int radius, int width, int height,
557a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org                  int srcStride, int dstStride)
5605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org{
577a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int srcStrideX = direction == kX ? 1 : srcStride;
587a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int dstStrideX = direction == kX ? 1 : dstStride;
597a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int srcStrideY = direction == kX ? srcStride : 1;
607a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int dstStrideY = direction == kX ? dstStride : 1;
6156dd630c41d662bcf2a3f08100f2c6accda05ba9senorblanco@chromium.org    radius = SkMin32(radius, width - 1);
6256dd630c41d662bcf2a3f08100f2c6accda05ba9senorblanco@chromium.org    const SkPMColor* upperSrc = src + radius * srcStrideX;
6305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    for (int x = 0; x < width; ++x) {
6405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        const SkPMColor* lp = src;
6505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        const SkPMColor* up = upperSrc;
6605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        SkPMColor* dptr = dst;
6705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        for (int y = 0; y < height; ++y) {
6805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            int minB = 255, minG = 255, minR = 255, minA = 255;
6905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            for (const SkPMColor* p = lp; p <= up; p += srcStrideX) {
7005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int b = SkGetPackedB32(*p);
7105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int g = SkGetPackedG32(*p);
7205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int r = SkGetPackedR32(*p);
7305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int a = SkGetPackedA32(*p);
7405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (b < minB) minB = b;
7505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (g < minG) minG = g;
7605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (r < minR) minR = r;
7705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (a < minA) minA = a;
7805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            }
7905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            *dptr = SkPackARGB32(minA, minR, minG, minB);
8005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            dptr += dstStrideY;
8105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            lp += srcStrideY;
8205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            up += srcStrideY;
8305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        }
8405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        if (x >= radius) src += srcStrideX;
8505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        if (x + radius < width - 1) upperSrc += srcStrideX;
8605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        dst += dstStrideX;
8705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
8805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
8905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
907a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgtemplate<MorphDirection direction>
9105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.orgstatic void dilate(const SkPMColor* src, SkPMColor* dst,
9205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                   int radius, int width, int height,
937a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org                   int srcStride, int dstStride)
9405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org{
957a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int srcStrideX = direction == kX ? 1 : srcStride;
967a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int dstStrideX = direction == kX ? 1 : dstStride;
977a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int srcStrideY = direction == kX ? srcStride : 1;
987a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    const int dstStrideY = direction == kX ? dstStride : 1;
9956dd630c41d662bcf2a3f08100f2c6accda05ba9senorblanco@chromium.org    radius = SkMin32(radius, width - 1);
10056dd630c41d662bcf2a3f08100f2c6accda05ba9senorblanco@chromium.org    const SkPMColor* upperSrc = src + radius * srcStrideX;
10105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    for (int x = 0; x < width; ++x) {
10205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        const SkPMColor* lp = src;
10305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        const SkPMColor* up = upperSrc;
10405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        SkPMColor* dptr = dst;
10505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        for (int y = 0; y < height; ++y) {
10605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            int maxB = 0, maxG = 0, maxR = 0, maxA = 0;
10705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            for (const SkPMColor* p = lp; p <= up; p += srcStrideX) {
10805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int b = SkGetPackedB32(*p);
10905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int g = SkGetPackedG32(*p);
11005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int r = SkGetPackedR32(*p);
11105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                int a = SkGetPackedA32(*p);
11205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (b > maxB) maxB = b;
11305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (g > maxG) maxG = g;
11405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (r > maxR) maxR = r;
11505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org                if (a > maxA) maxA = a;
11605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            }
11705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            *dptr = SkPackARGB32(maxA, maxR, maxG, maxB);
11805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            dptr += dstStrideY;
11905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            lp += srcStrideY;
12005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org            up += srcStrideY;
12105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        }
12205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        if (x >= radius) src += srcStrideX;
12305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        if (x + radius < width - 1) upperSrc += srcStrideX;
12405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        dst += dstStrideX;
12505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
12605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
12705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1280ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgstatic void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
12905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org{
1300ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
1310ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org          radiusX, bounds.width(), bounds.height(),
1320ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org          src.rowBytesAsPixels(), dst->rowBytesAsPixels());
13305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
13405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1350ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgstatic void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
13605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org{
1370ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
1380ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org          radiusY, bounds.height(), bounds.width(),
1390ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org          src.rowBytesAsPixels(), dst->rowBytesAsPixels());
14005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
14105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1420ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgbool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc procX,
1430ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                 SkMorphologyImageFilter::Proc procY,
1440ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                 Proxy* proxy,
1450ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                 const SkBitmap& source,
1464cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                                 const Context& ctx,
1470ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                 SkBitmap* dst,
148ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                 SkIPoint* offset) const {
14968400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    SkBitmap src = source;
1506776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
1514cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
15268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org        return false;
15368400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    }
15468400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org
15528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (src.colorType() != kN32_SkColorType) {
15605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        return false;
15705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
15805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1598fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    SkIRect bounds;
160118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1618fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        return false;
1628fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    }
1638fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org
16405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    SkAutoLockPixels alp(src);
16505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    if (!src.getPixels()) {
16605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        return false;
16705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
16805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
169848250415eddc54075f7eb8795e8db79e749c6abreed    if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
170cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
171cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
17205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1732bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
1742bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org                                     SkIntToScalar(this->radius().height()));
1754cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapVectors(&radius, 1);
1762bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    int width = SkScalarFloorToInt(radius.fX);
1772bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    int height = SkScalarFloorToInt(radius.fY);
17805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
17905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    if (width < 0 || height < 0) {
18005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        return false;
18105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
18205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1832bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    SkIRect srcBounds = bounds;
1842bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    srcBounds.offset(-srcOffset);
1852bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org
18605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    if (width == 0 && height == 0) {
1872bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org        src.extractSubset(dst, srcBounds);
1886776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = bounds.left();
1896776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fY = bounds.top();
19005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        return true;
19105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
19205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
19305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    SkBitmap temp;
194848250415eddc54075f7eb8795e8db79e749c6abreed    if (!temp.tryAllocPixels(dst->info())) {
19505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org        return false;
19605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
19705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
19805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    if (width > 0 && height > 0) {
1990ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        callProcX(procX, src, &temp, width, srcBounds);
2002bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org        SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height());
2010ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        callProcY(procY, temp, dst, height, tmpBounds);
20205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    } else if (width > 0) {
2030ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        callProcX(procX, src, dst, width, srcBounds);
20405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    } else if (height > 0) {
2050ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        callProcY(procY, src, dst, height, srcBounds);
20605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    }
2072bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    offset->fX = bounds.left();
2082bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    offset->fY = bounds.top();
20905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    return true;
21005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
21105054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
2120ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgbool SkErodeImageFilter::onFilterImage(Proxy* proxy,
2134cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                       const SkBitmap& source, const Context& ctx,
214ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                       SkBitmap* dst, SkIPoint* offset) const {
2150ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType);
2160ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    if (!erodeXProc) {
2170ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        erodeXProc = erode<kX>;
2181878a44c7490e3312a3b617fa03d2cf297b791e0skia.committer@gmail.com    }
2190ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType);
2200ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    if (!erodeYProc) {
2210ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        erodeYProc = erode<kY>;
2221878a44c7490e3312a3b617fa03d2cf297b791e0skia.committer@gmail.com    }
2234cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx, dst, offset);
2240ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org}
2251878a44c7490e3312a3b617fa03d2cf297b791e0skia.committer@gmail.com
2260ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgbool SkDilateImageFilter::onFilterImage(Proxy* proxy,
2274cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                        const SkBitmap& source, const Context& ctx,
228ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                        SkBitmap* dst, SkIPoint* offset) const {
2290ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType);
2300ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    if (!dilateXProc) {
2310ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        dilateXProc = dilate<kX>;
2321878a44c7490e3312a3b617fa03d2cf297b791e0skia.committer@gmail.com    }
2330ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType);
2340ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    if (!dilateYProc) {
2350ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org        dilateYProc = dilate<kY>;
2361878a44c7490e3312a3b617fa03d2cf297b791e0skia.committer@gmail.com    }
2374cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx, dst, offset);
23805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
23905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
240336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkMorphologyImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
241336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (getInput(0)) {
242336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        getInput(0)->computeFastBounds(src, dst);
243336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    } else {
244336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
245336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
246336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    dst->outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height()));
247336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org}
248336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
249c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.orgbool SkMorphologyImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
250c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                             SkIRect* dst) const {
251c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkIRect bounds = src;
252c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
253c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                     SkIntToScalar(this->radius().height()));
254c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    ctm.mapVectors(&radius, 1);
255c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    bounds.outset(SkScalarCeilToInt(radius.x()), SkScalarCeilToInt(radius.y()));
2561150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
2571150a6d151571fb6ee816dadec844ae7ab53948asenorblanco        return false;
2581150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    }
259c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    *dst = bounds;
260c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    return true;
261c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org}
262c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
2639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkErodeImageFilter::CreateProc(SkReadBuffer& buffer) {
2649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
2659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int width = buffer.readInt();
2669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int height = buffer.readInt();
2675e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return Create(width, height, common.getInput(0), &common.cropRect(), common.uniqueID());
2689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
2699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
2709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkDilateImageFilter::CreateProc(SkReadBuffer& buffer) {
2719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
2729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int width = buffer.readInt();
2739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int height = buffer.readInt();
2745e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return Create(width, height, common.getInput(0), &common.cropRect(), common.uniqueID());
2759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
2769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
277cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
27884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
27984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
28084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
28184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgclass GrGLMorphologyEffect;
28284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
28384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org/**
28484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org * Morphology effects. Depending upon the type of morphology, either the
28584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org * component-wise min (Erode_Type) or max (Dilate_Type) of all pixels in the
28684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org * kernel is selected as the new color. The new color is modulated by the input
28784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org * color.
28884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org */
28984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgclass GrMorphologyEffect : public Gr1DKernelEffect {
29084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
29184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgpublic:
29284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
29384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    enum MorphologyType {
29484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        kErode_MorphologyType,
29584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        kDilate_MorphologyType,
29684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    };
29784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
298b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrTexture* tex, Direction dir, int radius,
299b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       MorphologyType type) {
30055fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, type));
3010ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
3020ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
30384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    virtual ~GrMorphologyEffect();
30484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
30584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    MorphologyType type() const { return fType; }
30684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
30784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    static const char* Name() { return "Morphology"; }
30884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
309b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLMorphologyEffect GLProcessor;
31084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
311b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
31268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
31384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
31484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgprotected:
31584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
31684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    MorphologyType fType;
31784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
31884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgprivate:
319b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
32068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
3210ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    GrMorphologyEffect(GrTexture*, Direction, int radius, MorphologyType);
3220ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
323b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
32484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
32584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    typedef Gr1DKernelEffect INHERITED;
32684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org};
32784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
32884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
32984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
330b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLMorphologyEffect : public GrGLFragmentProcessor {
33184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgpublic:
332b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLMorphologyEffect (const GrBackendProcessorFactory&, const GrProcessor&);
33384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
33430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLProgramBuilder*,
335b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrFragmentProcessor&,
336b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrProcessorKey&,
33747d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                          const char* outputColor,
33847d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                          const char* inputColor,
33977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray&,
34047d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                          const TextureSamplerArray&) SK_OVERRIDE;
34184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
342b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
34384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
344b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
34584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
34684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgprivate:
34784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    int width() const { return GrMorphologyEffect::WidthFromRadius(fRadius); }
34884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
3497510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    int                                   fRadius;
3507510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrMorphologyEffect::MorphologyType    fType;
3517510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fImageIncrementUni;
35284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
353b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLFragmentProcessor INHERITED;
35484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org};
35584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
356b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendProcessorFactory& factory,
357b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                           const GrProcessor& proc)
35877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    : INHERITED(factory) {
359b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
36084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    fRadius = m.radius();
36184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    fType = m.type();
36284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
36384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
36430ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLMorphologyEffect::emitCode(GrGLProgramBuilder* builder,
365b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                    const GrFragmentProcessor&,
366b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                    const GrProcessorKey& key,
36747d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                                    const char* outputColor,
36847d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                                    const char* inputColor,
36977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                    const TransformedCoordsArray& coords,
37047d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com                                    const TextureSamplerArray& samplers) {
37130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
37284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                             kVec2f_GrSLType, "ImageIncrement");
37384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
37430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
37530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
37684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    const char* func;
37784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    switch (fType) {
37884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        case GrMorphologyEffect::kErode_MorphologyType:
37930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor);
38084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            func = "min";
38184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            break;
38284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        case GrMorphologyEffect::kDilate_MorphologyType:
38330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
38484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            func = "max";
38584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            break;
38684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        default:
38788cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org            SkFAIL("Unexpected type");
38884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            func = ""; // suppress warning
38984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            break;
39084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    }
39184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
39284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
39330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc);
39430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width());
39530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor);
39630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->appendTextureLookup(samplers[0], "coord");
39730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(");\n");
39830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\tcoord += %s;\n", imgInc);
39930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend("\t\t}\n");
400f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    SkString modulate;
401f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
40230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(modulate.c_str());
40384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
40484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
405b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLMorphologyEffect::GenKey(const GrProcessor& proc,
406b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  const GrGLCaps&, GrProcessorKeyBuilder* b) {
407b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
40863e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    uint32_t key = static_cast<uint32_t>(m.radius());
40984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    key |= (m.type() << 8);
41063e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    b->add32(key);
41184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
41284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
4137510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLMorphologyEffect::setData(const GrGLProgramDataManager& pdman,
414b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const GrProcessor& proc) {
415b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const Gr1DKernelEffect& kern = proc.cast<Gr1DKernelEffect>();
4162d0baded0f45dfde9dc8c25313ff14ea18c0c915bsalomon@google.com    GrTexture& texture = *kern.texture(0);
41784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    // the code we generated was for a specific kernel radius
41896ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org    SkASSERT(kern.radius() == fRadius);
41984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    float imageIncrement[2] = { 0 };
42084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    switch (kern.direction()) {
42184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        case Gr1DKernelEffect::kX_Direction:
42284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            imageIncrement[0] = 1.0f / texture.width();
42384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            break;
42484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        case Gr1DKernelEffect::kY_Direction:
42584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            imageIncrement[1] = 1.0f / texture.height();
42684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            break;
42784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        default:
42888cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org            SkFAIL("Unknown filter direction.");
42984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    }
4307510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
43184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
43284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
43384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
43484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
43584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgGrMorphologyEffect::GrMorphologyEffect(GrTexture* texture,
43684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                       Direction direction,
43784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                       int radius,
43884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                       MorphologyType type)
43984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    : Gr1DKernelEffect(texture, direction, radius)
44084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    , fType(type) {
44184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
44284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
44384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgGrMorphologyEffect::~GrMorphologyEffect() {
44484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
44584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
446b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrMorphologyEffect::getFactory() const {
447b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrMorphologyEffect>::getInstance();
44884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
44984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
450b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrMorphologyEffect::onIsEqual(const GrProcessor& sBase) const {
45149586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrMorphologyEffect& s = sBase.cast<GrMorphologyEffect>();
45268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    return (this->texture(0) == s.texture(0) &&
45384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            this->radius() == s.radius() &&
45484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            this->direction() == s.direction() &&
45584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org            this->type() == s.type());
45684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
45784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
45868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.comvoid GrMorphologyEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
45968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    // This is valid because the color components of the result of the kernel all come
46068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    // exactly from existing values in the source texture.
46168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    this->updateConstantColorComponentsForModulation(color, validFlags);
46268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com}
46368b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
46484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
46584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
466b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMorphologyEffect);
46784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
468b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrMorphologyEffect::TestCreate(SkRandom* random,
469b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrContext*,
470b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    const GrDrawTargetCaps&,
471b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrTexture* textures[]) {
472b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
473b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
47484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    Direction dir = random->nextBool() ? kX_Direction : kY_Direction;
47584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    static const int kMaxRadius = 10;
47684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    int radius = random->nextRangeU(1, kMaxRadius);
47784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    MorphologyType type = random->nextBool() ? GrMorphologyEffect::kErode_MorphologyType :
47884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                               GrMorphologyEffect::kDilate_MorphologyType;
47984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
4800ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    return GrMorphologyEffect::Create(textures[texIdx], dir, radius, type);
48184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
48284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
48384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgnamespace {
48484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
48584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.orgvoid apply_morphology_pass(GrContext* context,
48684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                           GrTexture* texture,
4878fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                           const SkIRect& srcRect,
4888fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                           const SkIRect& dstRect,
48984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                           int radius,
49084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                           GrMorphologyEffect::MorphologyType morphType,
49184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                           Gr1DKernelEffect::Direction direction) {
49284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    GrPaint paint;
493b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    paint.addColorProcessor(GrMorphologyEffect::Create(texture,
494b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       direction,
495b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       radius,
496b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       morphType))->unref();
4974469938e92d779dff05e745559e67907bbf21e78reed@google.com    context->drawRectToRect(paint, SkRect::Make(dstRect), SkRect::Make(srcRect));
49884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
49984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
5008fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.orgbool apply_morphology(const SkBitmap& input,
5018fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                      const SkIRect& rect,
5028fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                      GrMorphologyEffect::MorphologyType morphType,
5038fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                      SkISize radius,
5048fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                      SkBitmap* dst) {
5058fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    GrTexture* srcTexture = input.getTexture();
50649f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(srcTexture);
50784207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    GrContext* context = srcTexture->getContext();
50884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    srcTexture->ref();
5098fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    SkAutoTUnref<GrTexture> src(srcTexture);
5103cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com
5113cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com    GrContext::AutoMatrix am;
5123cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com    am.setIdentity(context);
5133cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com
514fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
51584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                                                    SkIntToScalar(srcTexture->height())));
5163cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com
5178fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
51884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    GrTextureDesc desc;
51984207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
520c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    desc.fWidth = rect.width();
521c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    desc.fHeight = rect.height();
522c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    desc.fConfig = kSkia8888_GrPixelConfig;
5238fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    SkIRect srcRect = rect;
5243cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com
52584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    if (radius.fWidth > 0) {
52684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        GrAutoScratchTexture ast(context, desc);
527673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        if (NULL == ast.texture()) {
528673d9732bf37df724500e04afcdf27d5c711ef60senorblanco            return false;
529673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        }
53084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
5318fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        apply_morphology_pass(context, src, srcRect, dstRect, radius.fWidth,
53284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                              morphType, Gr1DKernelEffect::kX_Direction);
5338fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
5348fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org                                              dstRect.width(), radius.fHeight);
535b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com        context->clear(&clearRect, GrMorphologyEffect::kErode_MorphologyType == morphType ?
536b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com                                   SK_ColorWHITE :
53756ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                                   SK_ColorTRANSPARENT, false);
5388fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        src.reset(ast.detach());
5398fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        srcRect = dstRect;
54084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    }
54184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    if (radius.fHeight > 0) {
54284207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        GrAutoScratchTexture ast(context, desc);
543673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        if (NULL == ast.texture()) {
544673d9732bf37df724500e04afcdf27d5c711ef60senorblanco            return false;
545673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        }
54684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org        GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
5478fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        apply_morphology_pass(context, src, srcRect, dstRect, radius.fHeight,
54884207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org                              morphType, Gr1DKernelEffect::kY_Direction);
5498fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        src.reset(ast.detach());
55084207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org    }
5516aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkImageFilter::WrapTexture(src, rect.width(), rect.height(), dst);
5526aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    return true;
55384207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org}
55484207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
55584207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org};
55684207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org
5570ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.orgbool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate,
5580ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                    Proxy* proxy,
5590ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                    const SkBitmap& src,
5604cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                                    const Context& ctx,
5610ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org                                                    SkBitmap* result,
562ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                    SkIPoint* offset) const {
5636aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkBitmap input = src;
5642bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
5654cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
566c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org        return false;
567c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    }
568c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    SkIRect bounds;
569118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
5708fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        return false;
5718fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    }
5722bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
5732bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org                                     SkIntToScalar(this->radius().height()));
5744cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    ctx.ctm().mapVectors(&radius, 1);
5752bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    int width = SkScalarFloorToInt(radius.fX);
5762bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    int height = SkScalarFloorToInt(radius.fY);
5778fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org
5788fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    if (width < 0 || height < 0) {
5798fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        return false;
5808fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    }
5818fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org
5822bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    SkIRect srcBounds = bounds;
5832bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org    srcBounds.offset(-srcOffset);
5848fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    if (width == 0 && height == 0) {
5852bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org        input.extractSubset(result, srcBounds);
5866776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fX = bounds.left();
5876776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org        offset->fY = bounds.top();
5888fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        return true;
5898fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    }
5908fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org
5910ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDilate_MorphologyType : GrMorphologyEffect::kErode_MorphologyType;
5920ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org    if (!apply_morphology(input, srcBounds, type,
5932bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org                          SkISize::Make(width, height), result)) {
5948fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org        return false;
5958fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    }
5966776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = bounds.left();
5976776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = bounds.top();
5988fcad9879173d627ee8638c52709d924034e34cesenorblanco@chromium.org    return true;
59905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
60005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
6014cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
602ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                         SkBitmap* result, SkIPoint* offset) const {
6034cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset);
6040ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org}
6050ded88d431a1872e21986984f009db2e84f52738senorblanco@chromium.org
6064cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
607ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                        SkBitmap* result, SkIPoint* offset) const {
6084cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset);
60905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org}
61005054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
61184207c42789e67ef377befb0c9057b9b73fbd6e3senorblanco@chromium.org#endif
612