1bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org/*
2bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * Copyright 2012 The Android Open Source Project
3bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org *
4bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
5bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * found in the LICENSE file.
6bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org */
7bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
8bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkImageFilter.h"
99f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
109f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org#include "SkBitmap.h"
1119fcc7494e68843cb9f2de819a7287ee216e3c5emtklein#include "SkChecksum.h"
12118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org#include "SkDevice.h"
1355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco#include "SkLazyPtr.h"
148c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkMatrixImageFilter.h"
158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
17bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkRect.h"
18f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org#include "SkTDynamicHash.h"
1955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco#include "SkTInternalLList.h"
20c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
21d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
22d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#include "GrContext.h"
236aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGrPixelRef.h"
246aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGr.h"
25d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
26bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
27195f62d07d6e996d188b9b2065da073f665a7c5fstephana#ifdef SK_BUILD_FOR_IOS
28195f62d07d6e996d188b9b2065da073f665a7c5fstephana  enum { kDefaultCacheSize = 2 * 1024 * 1024 };
29195f62d07d6e996d188b9b2065da073f665a7c5fstephana#else
30195f62d07d6e996d188b9b2065da073f665a7c5fstephana  enum { kDefaultCacheSize = 128 * 1024 * 1024 };
31195f62d07d6e996d188b9b2065da073f665a7c5fstephana#endif
3255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
3355b6d8be997a447ef9ce0f029697677a940bfc24senorblancostatic int32_t next_image_filter_unique_id() {
3455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    static int32_t gImageFilterUniqueID;
3555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
3655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // Never return 0.
3755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    int32_t id;
3855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    do {
3955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        id = sk_atomic_inc(&gImageFilterUniqueID) + 1;
4055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    } while (0 == id);
4155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    return id;
4255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
4355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
44be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancostruct SkImageFilter::Cache::Key {
4555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    Key(const uint32_t uniqueID, const SkMatrix& matrix, const SkIRect& clipBounds, uint32_t srcGenID)
4655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco      : fUniqueID(uniqueID), fMatrix(matrix), fClipBounds(clipBounds), fSrcGenID(srcGenID) {
4755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        // Assert that Key is tightly-packed, since it is hashed.
4855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SK_COMPILE_ASSERT(sizeof(Key) == sizeof(uint32_t) + sizeof(SkMatrix) + sizeof(SkIRect) +
4955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                                         sizeof(uint32_t), image_filter_key_tight_packing);
5055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fMatrix.getType();  // force initialization of type, so hashes match
5155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
5255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID;
5355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkMatrix fMatrix;
5455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkIRect fClipBounds;
5555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fSrcGenID;
5655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool operator==(const Key& other) const {
5755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        return fUniqueID == other.fUniqueID
5855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fMatrix == other.fMatrix
5955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fClipBounds == other.fClipBounds
6055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fSrcGenID == other.fSrcGenID;
6155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
6255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco};
6355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
64b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedSkImageFilter::Common::~Common() {
65b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    for (int i = 0; i < fInputs.count(); ++i) {
66b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkSafeUnref(fInputs[i]);
67b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
68b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
69b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
70b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedvoid SkImageFilter::Common::allocInputs(int count) {
71b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    const size_t size = count * sizeof(SkImageFilter*);
72b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    fInputs.reset(count);
73b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    sk_bzero(fInputs.get(), size);
74b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
75b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
76b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedvoid SkImageFilter::Common::detachInputs(SkImageFilter** inputs) {
77b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    const size_t size = fInputs.count() * sizeof(SkImageFilter*);
78b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    memcpy(inputs, fInputs.get(), size);
79b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    sk_bzero(fInputs.get(), size);
80b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
81b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
82b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedbool SkImageFilter::Common::unflatten(SkReadBuffer& buffer, int expectedCount) {
839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int count = buffer.readInt();
849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.validate(count >= 0)) {
859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return false;
86b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.validate(expectedCount < 0 || count == expectedCount)) {
88b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        return false;
89b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
90b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
91b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    this->allocInputs(count);
92b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    for (int i = 0; i < count; i++) {
93b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        if (buffer.readBool()) {
94b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed            fInputs[i] = buffer.readImageFilter();
95b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        }
96b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        if (!buffer.isValid()) {
97b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed            return false;
98b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        }
99b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
100b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    SkRect rect;
101b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    buffer.readRect(&rect);
102b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    if (!buffer.isValid() || !buffer.validate(SkIsValidRect(rect))) {
103b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        return false;
104b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
105148ec59001ca7d7e54aec580a048c6dd2a085991mtklein
106b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    uint32_t flags = buffer.readUInt();
107b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    fCropRect = CropRect(rect, flags);
1084a22a433bfb972dcd96f76e3d3b0613c26d8fc86senorblanco    if (buffer.isVersionLT(SkReadBuffer::kImageFilterNoUniqueID_Version)) {
1094a22a433bfb972dcd96f76e3d3b0613c26d8fc86senorblanco
1104a22a433bfb972dcd96f76e3d3b0613c26d8fc86senorblanco        (void) buffer.readUInt();
1114a22a433bfb972dcd96f76e3d3b0613c26d8fc86senorblanco    }
112b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    return buffer.isValid();
113b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
114b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
115b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed///////////////////////////////////////////////////////////////////////////////////////////////////
116b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
11724e06d5244ae96e440410e1d76e039983b2efac9senorblancoSkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
118194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(inputCount),
119194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[inputCount]),
12055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    fUsesSrcInput(false),
12155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)),
12224e06d5244ae96e440410e1d76e039983b2efac9senorblanco    fUniqueID(next_image_filter_unique_id()) {
1238d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < inputCount; ++i) {
12455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (NULL == inputs[i] || inputs[i]->usesSrcInput()) {
12555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            fUsesSrcInput = true;
12655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
1279f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        fInputs[i] = inputs[i];
1289f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeRef(fInputs[i]);
1299f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1309f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1319f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1329f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.orgSkImageFilter::~SkImageFilter() {
1338d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
1349f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeUnref(fInputs[i]);
1359f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1369f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    delete[] fInputs;
1379f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1389f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
13955b6d8be997a447ef9ce0f029697677a940bfc24senorblancoSkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer)
14024e06d5244ae96e440410e1d76e039983b2efac9senorblanco  : fUsesSrcInput(false)
14124e06d5244ae96e440410e1d76e039983b2efac9senorblanco  , fUniqueID(next_image_filter_unique_id()) {
142b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    Common common;
143b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    if (common.unflatten(buffer, inputCount)) {
144b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fCropRect = common.cropRect();
145b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fInputCount = common.inputCount();
146b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fInputs = SkNEW_ARRAY(SkImageFilter*, fInputCount);
147b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        common.detachInputs(fInputs);
14855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        for (int i = 0; i < fInputCount; ++i) {
14955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (NULL == fInputs[i] || fInputs[i]->usesSrcInput()) {
15055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fUsesSrcInput = true;
15155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
15255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
153ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    } else {
154ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputCount = 0;
155ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = NULL;
1569f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1598b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkImageFilter::flatten(SkWriteBuffer& buffer) const {
1608d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    buffer.writeInt(fInputCount);
1618d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
1629f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkImageFilter* input = getInput(i);
1639f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        buffer.writeBool(input != NULL);
1649f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        if (input != NULL) {
1659f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org            buffer.writeFlattenable(input);
1669f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
1679f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1683f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeRect(fCropRect.rect());
1693f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeUInt(fCropRect.flags());
1709f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1719f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
172bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
1734cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                const Context& context,
174ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const {
175bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(result);
1766776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkASSERT(offset);
17755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0;
178be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID);
179be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    if (context.cache()) {
18055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (context.cache()->get(key, result, offset)) {
18155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return true;
18255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
183f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
184bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    /*
185bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  Give the proxy first shot at the filter. If it returns false, ask
186bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  the filter to do it.
187bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     */
188f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
189f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        this->onFilterImage(proxy, src, context, result, offset)) {
190be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        if (context.cache()) {
19155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            context.cache()->set(key, *result, *offset);
19255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
193f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
194f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
195f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
196bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
197bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
198bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
199c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                 SkIRect* dst) const {
200bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(dst);
201bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return this->onFilterBounds(src, ctm, dst);
202bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
203bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
204336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
205336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (0 == fInputCount) {
206336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
207336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        return;
208336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
209336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getInput(0)) {
210336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getInput(0)->computeFastBounds(src, dst);
211336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    } else {
212336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
213336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
214336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    for (int i = 1; i < fInputCount; i++) {
215336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        SkImageFilter* input = this->getInput(i);
216336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        if (input) {
217336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            SkRect bounds;
218336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            input->computeFastBounds(src, &bounds);
219336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(bounds);
220336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        } else {
221336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(src);
222336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        }
223336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
224336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org}
225336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2264cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&,
227ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                  SkBitmap*, SkIPoint*) const {
228bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
229bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
230bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
231bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::canFilterImageGPU() const {
232b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return this->asFragmentProcessor(NULL, NULL, SkMatrix::I(), SkIRect());
233bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
234bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
2354cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
236ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                   SkBitmap* result, SkIPoint* offset) const {
237d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
2386aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkBitmap input = src;
239d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(fInputCount == 1);
240aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
2416aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->getInput(0) &&
2424cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
243d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org        return false;
244d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    }
245b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrTexture* srcTexture = input.getTexture();
2464e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkIRect bounds;
247118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
2484e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        return false;
2494e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
2504e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect srcRect = SkRect::Make(bounds);
2514e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
252d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext* context = srcTexture->getContext();
253d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
254f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc desc;
255f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    desc.fFlags = kRenderTarget_GrSurfaceFlag,
2564e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fWidth = bounds.width();
2574e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fHeight = bounds.height();
258d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fConfig = kRGBA_8888_GrPixelConfig;
259d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
260d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(
261d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        desc, GrTextureProvider::kApprox_ScratchTexMatch));
262e30597375c19dfb5197fd065a3d1768401eb00fabsalomon    if (!dst) {
263673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        return false;
264673d9732bf37df724500e04afcdf27d5c711ef60senorblanco    }
26525d9c154087d2132a51d1ca74a104726f60ef380joshualitt
266570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    // setup new clip
267570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    GrClip clip(dstRect);
268570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
269b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrFragmentProcessor* fp;
270aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fX = bounds.left();
271aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fY = bounds.top();
272aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    bounds.offset(-srcOffset);
2734cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkMatrix matrix(ctx.ctm());
274fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
275b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon    if (this->asFragmentProcessor(&fp, srcTexture, matrix, bounds)) {
276b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon        SkASSERT(fp);
277b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon        GrPaint paint;
278b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon        paint.addColorProcessor(fp)->unref();
279570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt        context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(), dstRect,
280570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                                     srcRect);
2814e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
282e30597375c19dfb5197fd065a3d1768401eb00fabsalomon        WrapTexture(dst, bounds.width(), bounds.height(), result);
283b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon        return true;
284b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon    }
285d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
286b501ecd0d7aa1c49c8c7f407ac6d51f5dc93122fbsalomon    return false;
287bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
288bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
289118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
290118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  const SkIPoint& srcOffset, SkIRect* bounds) const {
291118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
292118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
293118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(srcOffset);
294fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkRect cropRect;
295118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
296b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    const SkIRect cropRectI = cropRect.roundOut();
2973f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
298118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
299118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
300118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
301118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
302118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!srcBounds.intersect(ctx.clipBounds())) {
303118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
304118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
305118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
306118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    return true;
307118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org}
308118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
309118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
310118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
311118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
312118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
313118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(*srcOffset);
314118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkRect cropRect;
315118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
316b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    const SkIRect cropRectI = cropRect.roundOut();
317118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
318118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
319118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
320118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
321118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
322118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
323118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!bounds->intersect(ctx.clipBounds())) {
324118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
325118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
326118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (srcBounds.contains(*bounds)) {
327118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = src;
328118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
329118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    } else {
330118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
331118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        if (!device) {
332118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org            return false;
333118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        }
334118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkCanvas canvas(device);
335118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.clear(0x00000000);
336118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
337118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
338118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = device->accessBitmap(false);
339118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
340118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
341194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org}
342194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
343bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
344c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                   SkIRect* dst) const {
345c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (fInputCount < 1) {
3468f3937d9fcb28018ec14db6697d41b645716d589senorblanco        *dst = src;
3478f3937d9fcb28018ec14db6697d41b645716d589senorblanco        return true;
348c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
349c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
350c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkIRect bounds;
351c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    for (int i = 0; i < fInputCount; ++i) {
352c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkImageFilter* filter = this->getInput(i);
353c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkIRect rect = src;
354c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (filter && !filter->filterBounds(src, ctm, &rect)) {
355c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            return false;
356c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
357c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (0 == i) {
358c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds = rect;
359c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        } else {
360c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds.join(rect);
361c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
362c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
363c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
364c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // don't modify dst until now, so we don't accidentally change it in the
365c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // loop, but then return false on the next filter.
366c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    *dst = bounds;
367bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return true;
368bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
369bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
370b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkImageFilter::asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
371b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                        const SkIRect&) const {
372bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
373bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
3748d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
3758c874eee943bdea0fab5b4d2707083c863e37c55senorblancoSkImageFilter* SkImageFilter::CreateMatrixFilter(const SkMatrix& matrix,
3768c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                                 SkFilterQuality filterQuality,
3778c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                                 SkImageFilter* input) {
3788c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    return SkMatrixImageFilter::Create(matrix, filterQuality, input);
3798c874eee943bdea0fab5b4d2707083c863e37c55senorblanco}
3808c874eee943bdea0fab5b4d2707083c863e37c55senorblanco
3816aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#if SK_SUPPORT_GPU
3826aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3836aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgvoid SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
3846aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
385a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    result->setInfo(info);
3866aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
3876aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3886aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3896aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgbool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy,
3904cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                      const SkBitmap& src, const Context& ctx,
3916aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                                      SkBitmap* result, SkIPoint* offset) const {
3926aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
3936aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // matrix with no clip and that the matrix, clip, and render target set before this function was
3946aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // called are restored before we return to the caller.
3956aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext* context = src.getTexture()->getContext();
396570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt
3976aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->canFilterImageGPU()) {
3984cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        return this->filterImageGPU(proxy, src, ctx, result, offset);
3996aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    } else {
4004cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        if (this->filterImage(proxy, src, ctx, result, offset)) {
4016aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            if (!result->getTexture()) {
402466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                const SkImageInfo info = result->info();
403466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                if (kUnknown_SkColorType == info.colorType()) {
4046aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                    return false;
4056aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                }
406bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                SkAutoTUnref<GrTexture> resultTex(GrRefCachedBitmapTexture(context, *result, NULL));
407bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, resultTex)))->unref();
4086aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            }
4096aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return true;
4106aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        } else {
4116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return false;
4126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        }
4136aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    }
4146aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
4156aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
416f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
41755b6d8be997a447ef9ce0f029697677a940bfc24senorblanconamespace {
41855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
419be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoclass CacheImpl : public SkImageFilter::Cache {
42055b6d8be997a447ef9ce0f029697677a940bfc24senorblancopublic:
421be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) {
42255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
423be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    virtual ~CacheImpl() {
42455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkTDynamicHash<Value, Key>::Iter iter(&fLookup);
42555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
42655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        while (!iter.done()) {
42755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            Value* v = &*iter;
42855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            ++iter;
42955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            delete v;
43055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
43155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
43255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    struct Value {
43355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset)
43455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            : fKey(key), fBitmap(bitmap), fOffset(offset) {}
43555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Key fKey;
43655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkBitmap fBitmap;
43755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkIPoint fOffset;
43855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        static const Key& GetKey(const Value& v) {
43955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return v.fKey;
44055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
44155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        static uint32_t Hash(const Key& key) {
44255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
44355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
44455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value);
44555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    };
44636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const override {
44755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkAutoMutexAcquire mutex(fMutex);
44855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (Value* v = fLookup.find(key)) {
44955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            *result = v->fBitmap;
45055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            *offset = v->fOffset;
45155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (v != fLRU.head()) {
45255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fLRU.remove(v);
45355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fLRU.addToHead(v);
45455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
45555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return true;
45655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
45755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        return false;
45855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
45936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) override {
46055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkAutoMutexAcquire mutex(fMutex);
46155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (Value* v = fLookup.find(key)) {
46255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            removeInternal(v);
46355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
46455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Value* v = new Value(key, result, offset);
46555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLookup.add(v);
46655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLRU.addToHead(v);
46755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fCurrentBytes += result.getSize();
46855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        while (fCurrentBytes > fMaxBytes) {
46955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            Value* tail = fLRU.tail();
47055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkASSERT(tail);
47155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (tail == v) {
47255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                break;
47355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
47455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            removeInternal(tail);
47555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
47655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
47755b6d8be997a447ef9ce0f029697677a940bfc24senorblancoprivate:
47855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    void removeInternal(Value* v) {
47955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fCurrentBytes -= v->fBitmap.getSize();
48055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLRU.remove(v);
48155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLookup.remove(v->fKey);
48255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        delete v;
48355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
48455b6d8be997a447ef9ce0f029697677a940bfc24senorblancoprivate:
48555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkTDynamicHash<Value, Key>         fLookup;
48655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    mutable SkTInternalLList<Value>    fLRU;
48755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    size_t                             fMaxBytes;
48855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    size_t                             fCurrentBytes;
48955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    mutable SkMutex                    fMutex;
49055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco};
49155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
492be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* CreateCache() {
493be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    return SkImageFilter::Cache::Create(kDefaultCacheSize);
49455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
49555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
49655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco} // namespace
49755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
498be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* SkImageFilter::Cache::Create(size_t maxBytes) {
499be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    return SkNEW_ARGS(CacheImpl, (maxBytes));
50055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
50155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
502148ec59001ca7d7e54aec580a048c6dd2a085991mtkleinSK_DECLARE_STATIC_LAZY_PTR(SkImageFilter::Cache, cache, CreateCache);
503148ec59001ca7d7e54aec580a048c6dd2a085991mtklein
504be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* SkImageFilter::Cache::Get() {
50555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    return cache.get();
50655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
507