15faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org/*
25faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * Copyright 2012 The Android Open Source Project
35faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org *
45faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
55faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org * found in the LICENSE file.
65faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org */
75faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
85faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkMatrixConvolutionImageFilter.h"
95faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkBitmap.h"
105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkColorPriv.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org#include "SkRect.h"
148640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org#include "SkUnPreMultiply.h"
155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
163bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#if SK_SUPPORT_GPU
17ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt#include "effects/GrMatrixConvolutionEffect.h"
183bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#endif
193bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
20aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White// We need to be able to read at most SK_MaxS32 bytes, so divide that
21aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White// by the size of a scalar to know how many scalars we can read.
22aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen Whitestatic const int32_t gMaxKernelSize = SK_MaxS32 / sizeof(SkScalar);
23aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White
247938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgSkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(
257938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    const SkISize& kernelSize,
267938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    const SkScalar* kernel,
277938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkScalar gain,
287938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkScalar bias,
29cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    const SkIPoint& kernelOffset,
307938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    TileMode tileMode,
317938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    bool convolveAlpha,
327938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkImageFilter* input,
335e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    const CropRect* cropRect,
345e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    uint32_t uniqueID)
355e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco  : INHERITED(1, &input, cropRect, uniqueID),
365faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize(kernelSize),
375faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fGain(gain),
385faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fBias(bias),
39cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    fKernelOffset(kernelOffset),
408640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fTileMode(tileMode),
418640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fConvolveAlpha(convolveAlpha) {
42aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    size_t size = (size_t) sk_64_mul(fKernelSize.width(), fKernelSize.height());
435faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernel = SkNEW_ARRAY(SkScalar, size);
445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    memcpy(fKernel, kernel, size * sizeof(SkScalar));
453bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org    SkASSERT(kernelSize.fWidth >= 1 && kernelSize.fHeight >= 1);
46cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    SkASSERT(kernelOffset.fX >= 0 && kernelOffset.fX < kernelSize.fWidth);
47cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    SkASSERT(kernelOffset.fY >= 0 && kernelOffset.fY < kernelSize.fHeight);
485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
50aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen WhiteSkMatrixConvolutionImageFilter* SkMatrixConvolutionImageFilter::Create(
51aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    const SkISize& kernelSize,
52aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    const SkScalar* kernel,
53aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    SkScalar gain,
54aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    SkScalar bias,
55aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    const SkIPoint& kernelOffset,
56aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    TileMode tileMode,
57aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    bool convolveAlpha,
58aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    SkImageFilter* input,
59aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    const CropRect* cropRect,
60aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    uint32_t uniqueID) {
61aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    if (kernelSize.width() < 1 || kernelSize.height() < 1) {
62aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White        return NULL;
63aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    }
64aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    if (gMaxKernelSize / kernelSize.fWidth < kernelSize.fHeight) {
65aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White        return NULL;
66aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    }
67aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    if (!kernel) {
68aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White        return NULL;
69aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    }
70aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White    return SkNEW_ARGS(SkMatrixConvolutionImageFilter, (kernelSize, kernel, gain, bias,
71aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White                                                       kernelOffset, tileMode, convolveAlpha,
72aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White                                                       input, cropRect, uniqueID));
73aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White}
74aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White
759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedstatic bool tile_mode_is_valid(SkMatrixConvolutionImageFilter::TileMode tileMode) {
779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    switch (tileMode) {
789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        case SkMatrixConvolutionImageFilter::kClamp_TileMode:
799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        case SkMatrixConvolutionImageFilter::kRepeat_TileMode:
809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode:
819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return true;
829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        default:
839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            break;
849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return false;
869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
888b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkReadBuffer& buffer)
89ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    : INHERITED(1, buffer) {
905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize.fWidth = buffer.readInt();
915faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fKernelSize.fHeight = buffer.readInt();
92d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    if ((fKernelSize.fWidth >= 1) && (fKernelSize.fHeight >= 1) &&
93d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org        // Make sure size won't be larger than a signed int,
94d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org        // which would still be extremely large for a kernel,
95d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org        // but we don't impose a hard limit for kernel size
96aafcb54f27d30c63602a0a0232f0b9fc8b310d19Stephen White        (gMaxKernelSize / fKernelSize.fWidth >= fKernelSize.fHeight)) {
97025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        size_t size = fKernelSize.fWidth * fKernelSize.fHeight;
98d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org        fKernel = SkNEW_ARRAY(SkScalar, size);
99025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        SkDEBUGCODE(bool success =) buffer.readScalarArray(fKernel, size);
100025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        SkASSERT(success);
101d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    } else {
102d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org        fKernel = 0;
103d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    }
1045faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fGain = buffer.readScalar();
1055faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fBias = buffer.readScalar();
106cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    fKernelOffset.fX = buffer.readInt();
107cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    fKernelOffset.fY = buffer.readInt();
1085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    fTileMode = (TileMode) buffer.readInt();
1098640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    fConvolveAlpha = buffer.readBool();
110d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    buffer.validate((fKernel != 0) &&
111d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org                    SkScalarIsFinite(fGain) &&
112c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                    SkScalarIsFinite(fBias) &&
11356d135c03e1d38f0b9e17d79a3cbf8db2a915086sugoi                    tile_mode_is_valid(fTileMode) &&
11456d135c03e1d38f0b9e17d79a3cbf8db2a915086sugoi                    (fKernelOffset.fX >= 0) && (fKernelOffset.fX < fKernelSize.fWidth) &&
11556d135c03e1d38f0b9e17d79a3cbf8db2a915086sugoi                    (fKernelOffset.fY >= 0) && (fKernelOffset.fY < fKernelSize.fHeight));
1165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkMatrixConvolutionImageFilter::CreateProc(SkReadBuffer& buffer) {
1209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkISize kernelSize;
1229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    kernelSize.fWidth = buffer.readInt();
1239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    kernelSize.fHeight = buffer.readInt();
1249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int count = buffer.getArrayCount();
1259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int64_t kernelArea = sk_64_mul(kernelSize.width(), kernelSize.height());
1279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.validate(kernelArea == count)) {
1289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
1299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoSTArray<16, SkScalar> kernel(count);
1319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.readScalarArray(kernel.get(), count)) {
1329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
1339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar gain = buffer.readScalar();
1359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar bias = buffer.readScalar();
1369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkIPoint kernelOffset;
1379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    kernelOffset.fX = buffer.readInt();
1389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    kernelOffset.fY = buffer.readInt();
1399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    TileMode tileMode = (TileMode)buffer.readInt();
1409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    bool convolveAlpha = buffer.readBool();
1419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return Create(kernelSize, kernel.get(), gain, bias, kernelOffset, tileMode, convolveAlpha,
1425e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                  common.getInput(0), &common.cropRect(), common.uniqueID());
1439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMatrixConvolutionImageFilter::flatten(SkWriteBuffer& buffer) const {
1465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    this->INHERITED::flatten(buffer);
1475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt(fKernelSize.fWidth);
1485faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt(fKernelSize.fHeight);
1495faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalarArray(fKernel, fKernelSize.fWidth * fKernelSize.fHeight);
1505faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fGain);
1515faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeScalar(fBias);
152cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    buffer.writeInt(fKernelOffset.fX);
153cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    buffer.writeInt(fKernelOffset.fY);
1545faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    buffer.writeInt((int) fTileMode);
1558640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    buffer.writeBool(fConvolveAlpha);
1565faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1575faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1585faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgSkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() {
1595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    delete[] fKernel;
1605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
1615faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1625faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass UncheckedPixelFetcher {
1635faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
1647938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
1655faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
1665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1675faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
1685faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1695faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass ClampPixelFetcher {
1705faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
1717938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
1727938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        x = SkPin32(x, bounds.fLeft, bounds.fRight - 1);
1737938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        y = SkPin32(y, bounds.fTop, bounds.fBottom - 1);
1745faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
1755faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1765faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
1775faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1785faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass RepeatPixelFetcher {
1795faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
1807938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
1817938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        x = (x - bounds.left()) % bounds.width() + bounds.left();
1827938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        y = (y - bounds.top()) % bounds.height() + bounds.top();
1837938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        if (x < bounds.left()) {
1847938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org            x += bounds.width();
1855faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
1867938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        if (y < bounds.top()) {
1877938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org            y += bounds.height();
1885faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
1895faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return *src.getAddr32(x, y);
1905faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
1915faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
1925faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
1935faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgclass ClampToBlackPixelFetcher {
1945faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgpublic:
1957938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
1967938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bounds.fBottom) {
1975faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            return 0;
1985faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        } else {
1995faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            return *src.getAddr32(x, y);
2005faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
2015faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
2025faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org};
2035faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2048640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgtemplate<class PixelFetcher, bool convolveAlpha>
2057938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
2067938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                  SkBitmap* result,
2078c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org                                                  const SkIRect& r,
208ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                  const SkIRect& bounds) const {
2098c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkIRect rect(r);
2108c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    if (!rect.intersect(bounds)) {
2119195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org        return;
2129195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    }
2135faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    for (int y = rect.fTop; y < rect.fBottom; ++y) {
2147938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bounds.fTop);
2155faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        for (int x = rect.fLeft; x < rect.fRight; ++x) {
2165faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0;
2175faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            for (int cy = 0; cy < fKernelSize.fHeight; cy++) {
2185faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                for (int cx = 0; cx < fKernelSize.fWidth; cx++) {
2197938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                    SkPMColor s = PixelFetcher::fetch(src,
220cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org                                                      x + cx - fKernelOffset.fX,
221cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org                                                      y + cy - fKernelOffset.fY,
2227938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                      bounds);
2235faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    SkScalar k = fKernel[cy * fKernelSize.fWidth + cx];
2248640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                    if (convolveAlpha) {
2258640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                        sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k);
2268640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                    }
2275faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k);
2285faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k);
2295faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                    sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k);
2305faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                }
2315faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            }
2328640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            int a = convolveAlpha
2338640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                  ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBias), 255)
2343bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org                  : 255;
235cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBias), a);
236cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBias), a);
237cc9471c36d3967270f7eb26f8b53ce0f17bc9fbbsenorblanco@chromium.org            int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBias), a);
2388640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            if (!convolveAlpha) {
2397938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                a = SkGetPackedA32(PixelFetcher::fetch(src, x, y, bounds));
2408640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                *dptr++ = SkPreMultiplyARGB(a, r, g, b);
2418640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            } else {
2428640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org                *dptr++ = SkPackARGB32(a, r, g, b);
2438640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            }
2445faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        }
2455faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
2465faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
2475faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2488640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgtemplate<class PixelFetcher>
2497938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
2507938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                  SkBitmap* result,
2517938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                  const SkIRect& rect,
252ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                  const SkIRect& bounds) const {
2538640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (fConvolveAlpha) {
2547938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        filterPixels<PixelFetcher, true>(src, result, rect, bounds);
2558640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    } else {
2567938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        filterPixels<PixelFetcher, false>(src, result, rect, bounds);
2578640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
2588640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org}
2598640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
2607938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src,
2617938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                          SkBitmap* result,
2627938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                          const SkIRect& rect,
263ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                          const SkIRect& bounds) const {
2647938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterPixels<UncheckedPixelFetcher>(src, result, rect, bounds);
2655faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
2665faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
2677938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgvoid SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src,
2687938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                        SkBitmap* result,
2697938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                                        const SkIRect& rect,
270ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                        const SkIRect& bounds) const {
2715faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    switch (fTileMode) {
2725faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kClamp_TileMode:
2737938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org            filterPixels<ClampPixelFetcher>(src, result, rect, bounds);
2745faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
2755faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kRepeat_TileMode:
2767938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org            filterPixels<RepeatPixelFetcher>(src, result, rect, bounds);
2775faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
2785faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        case kClampToBlack_TileMode:
2797938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org            filterPixels<ClampToBlackPixelFetcher>(src, result, rect, bounds);
2805faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org            break;
2815faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
2825faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
2835faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
284377c14a1e648f4427bd11474fad8ac264d98aff2senorblanco@chromium.org// FIXME:  This should be refactored to SkImageFilterUtils for
2858640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org// use by other filters.  For now, we assume the input is always
2868640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org// premultiplied and unpremultiply it
2878640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.orgstatic SkBitmap unpremultiplyBitmap(const SkBitmap& src)
2888640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org{
2898640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    SkAutoLockPixels alp(src);
2908640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (!src.getPixels()) {
2918640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        return SkBitmap();
2928640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
2938640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    SkBitmap result;
294848250415eddc54075f7eb8795e8db79e749c6abreed    if (!result.tryAllocPixels(src.info())) {
2958640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        return SkBitmap();
2968640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
2978640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    for (int y = 0; y < src.height(); ++y) {
2988640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        const uint32_t* srcRow = src.getAddr32(0, y);
2998640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        uint32_t* dstRow = result.getAddr32(0, y);
3008640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        for (int x = 0; x < src.width(); ++x) {
3018640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org            dstRow[x] = SkUnPreMultiply::PMColorToColor(srcRow[x]);
3028640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        }
3038640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
3048640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    return result;
3058640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org}
3068640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
3075faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.orgbool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
3085faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   const SkBitmap& source,
3094cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                                   const Context& ctx,
3105faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org                                                   SkBitmap* result,
311ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                   SkIPoint* offset) const {
31268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    SkBitmap src = source;
3136776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
3144cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
31568400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org        return false;
31668400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org    }
31768400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org
31828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (src.colorType() != kN32_SkColorType) {
3195faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return false;
3205faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
3215faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
3227938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkIRect bounds;
323118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
3247938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org        return false;
3257938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    }
3267938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org
3278640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    if (!fConvolveAlpha && !src.isOpaque()) {
3288640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org        src = unpremultiplyBitmap(src);
3298640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org    }
3308640d5024d57da5508bdf7585849e3b1f1cb365bsenorblanco@chromium.org
3315faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkAutoLockPixels alp(src);
3325faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    if (!src.getPixels()) {
3335faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org        return false;
3345faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    }
3355faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
336848250415eddc54075f7eb8795e8db79e749c6abreed    if (!result->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
337cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
338cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
3395faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org
3406776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = bounds.fLeft;
3416776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = bounds.fTop;
3426776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    bounds.offset(-srcOffset);
343cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org    SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fKernelOffset.fX,
344cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org                                         bounds.top() + fKernelOffset.fY,
3457938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                         bounds.width() - fKernelSize.fWidth + 1,
3467938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                         bounds.height() - fKernelSize.fHeight + 1);
3477938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(), interior.top());
3487938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkIRect bottom = SkIRect::MakeLTRB(bounds.left(), interior.bottom(),
3497938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                       bounds.right(), bounds.bottom());
3507938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    SkIRect left = SkIRect::MakeLTRB(bounds.left(), interior.top(),
3517938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                     interior.left(), interior.bottom());
3525faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(),
3537938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org                                      bounds.right(), interior.bottom());
3547938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterBorderPixels(src, result, top, bounds);
3557938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterBorderPixels(src, result, left, bounds);
3567938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterInteriorPixels(src, result, interior, bounds);
3577938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterBorderPixels(src, result, right, bounds);
3587938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    filterBorderPixels(src, result, bottom, bounds);
3595faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org    return true;
3605faa2dc266ec933b3961f985e5718236f1ecbe47senorblanco@chromium.org}
3613bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
3620a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgbool SkMatrixConvolutionImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
3630a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                                    SkIRect* dst) const {
3640a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkIRect bounds = src;
3650a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    bounds.fRight += fKernelSize.width() - 1;
3660a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    bounds.fBottom += fKernelSize.height() - 1;
3670a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    bounds.offset(-fKernelOffset);
3680a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
3690a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        return false;
3700a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    }
3710a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    *dst = bounds;
3720a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    return true;
3730a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
3740a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
3753bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#if SK_SUPPORT_GPU
3763bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
3775ae5fc59b27a48711e514b3ede548b228e393e9bjoshualittstatic GrTextureDomain::Mode convert_tilemodes(
378ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt        SkMatrixConvolutionImageFilter::TileMode tileMode) {
3795ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt    switch (tileMode) {
3805ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt        case SkMatrixConvolutionImageFilter::kClamp_TileMode:
3815ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt            return GrTextureDomain::kClamp_Mode;
3825ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt        case SkMatrixConvolutionImageFilter::kRepeat_TileMode:
3835ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt            return GrTextureDomain::kRepeat_Mode;
3845ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt        case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode:
3855ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt            return GrTextureDomain::kDecal_Mode;
3865ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt        default:
3875ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt            SkASSERT(false);
3885ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt    }
3895ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt    return GrTextureDomain::kIgnore_Mode;
3903bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org}
3913bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org
392b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkMatrixConvolutionImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
393b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                         GrTexture* texture,
394b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                         const SkMatrix&,
395b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                         const SkIRect& bounds) const {
396b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (!fp) {
397d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org        return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE;
3983bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org    }
399d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE);
400b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    *fp = GrMatrixConvolutionEffect::Create(texture,
401b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            bounds,
402b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fKernelSize,
403b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fKernel,
404b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fGain,
405b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fBias,
406b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fKernelOffset,
407b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            convert_tilemodes(fTileMode),
408b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            fConvolveAlpha);
409d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    return true;
4103bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org}
4113bc16c8bc1ecb9ac4450f58093cc9e3edb8a50b8senorblanco@chromium.org#endif
412