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"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
16bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkRect.h"
17f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org#include "SkTDynamicHash.h"
1855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco#include "SkTInternalLList.h"
19c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
20d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
21d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#include "GrContext.h"
226aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGrPixelRef.h"
236aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGr.h"
24d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
25bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
2655b6d8be997a447ef9ce0f029697677a940bfc24senorblancoenum { kDefaultCacheSize = 128 * 1024 * 1024 };
2755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
2855b6d8be997a447ef9ce0f029697677a940bfc24senorblancostatic int32_t next_image_filter_unique_id() {
2955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    static int32_t gImageFilterUniqueID;
3055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
3155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // Never return 0.
3255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    int32_t id;
3355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    do {
3455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        id = sk_atomic_inc(&gImageFilterUniqueID) + 1;
3555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    } while (0 == id);
3655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    return id;
3755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
3855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
39be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancostruct SkImageFilter::Cache::Key {
4055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    Key(const uint32_t uniqueID, const SkMatrix& matrix, const SkIRect& clipBounds, uint32_t srcGenID)
4155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco      : fUniqueID(uniqueID), fMatrix(matrix), fClipBounds(clipBounds), fSrcGenID(srcGenID) {
4255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        // Assert that Key is tightly-packed, since it is hashed.
4355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SK_COMPILE_ASSERT(sizeof(Key) == sizeof(uint32_t) + sizeof(SkMatrix) + sizeof(SkIRect) +
4455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                                         sizeof(uint32_t), image_filter_key_tight_packing);
4555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fMatrix.getType();  // force initialization of type, so hashes match
4655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
4755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID;
4855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkMatrix fMatrix;
4955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkIRect fClipBounds;
5055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fSrcGenID;
5155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool operator==(const Key& other) const {
5255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        return fUniqueID == other.fUniqueID
5355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fMatrix == other.fMatrix
5455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fClipBounds == other.fClipBounds
5555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            && fSrcGenID == other.fSrcGenID;
5655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
5755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco};
5855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
59b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedSkImageFilter::Common::~Common() {
60b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    for (int i = 0; i < fInputs.count(); ++i) {
61b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkSafeUnref(fInputs[i]);
62b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
63b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
64b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
65b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedvoid SkImageFilter::Common::allocInputs(int count) {
66b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    const size_t size = count * sizeof(SkImageFilter*);
67b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    fInputs.reset(count);
68b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    sk_bzero(fInputs.get(), size);
69b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
70b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
71b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedvoid SkImageFilter::Common::detachInputs(SkImageFilter** inputs) {
72b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    const size_t size = fInputs.count() * sizeof(SkImageFilter*);
73b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    memcpy(inputs, fInputs.get(), size);
74b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    sk_bzero(fInputs.get(), size);
75b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
76b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
77b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reedbool SkImageFilter::Common::unflatten(SkReadBuffer& buffer, int expectedCount) {
789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const int count = buffer.readInt();
799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.validate(count >= 0)) {
809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return false;
81b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!buffer.validate(expectedCount < 0 || count == expectedCount)) {
83b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        return false;
84b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
85b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
86b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    this->allocInputs(count);
87b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    for (int i = 0; i < count; i++) {
88b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        if (buffer.readBool()) {
89b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed            fInputs[i] = buffer.readImageFilter();
90b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        }
91b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        if (!buffer.isValid()) {
92b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed            return false;
93b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        }
94b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
95b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    SkRect rect;
96b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    buffer.readRect(&rect);
97b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    if (!buffer.isValid() || !buffer.validate(SkIsValidRect(rect))) {
98b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        return false;
99b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    }
100b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
101b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    uint32_t flags = buffer.readUInt();
102b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    fCropRect = CropRect(rect, flags);
10355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    if (buffer.isVersionLT(SkReadBuffer::kImageFilterUniqueID_Version)) {
10455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fUniqueID = next_image_filter_unique_id();
10555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    } else {
10655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fUniqueID = buffer.readUInt();
10755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
108b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    return buffer.isValid();
109b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed}
110b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
111b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed///////////////////////////////////////////////////////////////////////////////////////////////////
112b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
1135e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblancoSkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect, uint32_t uniqueID)
114194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(inputCount),
115194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[inputCount]),
11655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    fUsesSrcInput(false),
11755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)),
1185e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    fUniqueID(uniqueID ? uniqueID : next_image_filter_unique_id()) {
1198d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < inputCount; ++i) {
12055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (NULL == inputs[i] || inputs[i]->usesSrcInput()) {
12155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            fUsesSrcInput = true;
12255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
1239f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        fInputs[i] = inputs[i];
1249f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeRef(fInputs[i]);
1259f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1269f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1279f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1289f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.orgSkImageFilter::~SkImageFilter() {
1298d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
1309f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeUnref(fInputs[i]);
1319f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1329f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    delete[] fInputs;
1339f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1349f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
13555b6d8be997a447ef9ce0f029697677a940bfc24senorblancoSkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer)
13655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco  : fUsesSrcInput(false) {
137b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    Common common;
138b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    if (common.unflatten(buffer, inputCount)) {
139b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fCropRect = common.cropRect();
140b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fInputCount = common.inputCount();
141b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        fInputs = SkNEW_ARRAY(SkImageFilter*, fInputCount);
142b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        common.detachInputs(fInputs);
14355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        for (int i = 0; i < fInputCount; ++i) {
14455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (NULL == fInputs[i] || fInputs[i]->usesSrcInput()) {
14555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fUsesSrcInput = true;
14655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
14755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
14855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fUniqueID = buffer.isCrossProcess() ? next_image_filter_unique_id() : common.uniqueID();
149ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    } else {
150ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputCount = 0;
151ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = NULL;
1529f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1539f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1549f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
1558b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkImageFilter::flatten(SkWriteBuffer& buffer) const {
1568d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    buffer.writeInt(fInputCount);
1578d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
1589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkImageFilter* input = getInput(i);
1599f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        buffer.writeBool(input != NULL);
1609f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        if (input != NULL) {
1619f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org            buffer.writeFlattenable(input);
1629f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
1639f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
1643f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeRect(fCropRect.rect());
1653f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeUInt(fCropRect.flags());
16655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    buffer.writeUInt(fUniqueID);
1679f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
1689f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
169bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
1704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                const Context& context,
171ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const {
172bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(result);
1736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkASSERT(offset);
17455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0;
175be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID);
176be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    if (context.cache()) {
17755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (context.cache()->get(key, result, offset)) {
17855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return true;
17955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
180f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
181bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    /*
182bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  Give the proxy first shot at the filter. If it returns false, ask
183bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  the filter to do it.
184bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     */
185f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
186f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        this->onFilterImage(proxy, src, context, result, offset)) {
187be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        if (context.cache()) {
18855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            context.cache()->set(key, *result, *offset);
18955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
190f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
191f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
192f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
193bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
194bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
195bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
196c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                 SkIRect* dst) const {
197bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(&src);
198bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(dst);
199bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return this->onFilterBounds(src, ctm, dst);
200bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
201bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
202336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
203336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (0 == fInputCount) {
204336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
205336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        return;
206336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
207336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getInput(0)) {
208336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getInput(0)->computeFastBounds(src, dst);
209336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    } else {
210336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
211336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
212336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    for (int i = 1; i < fInputCount; i++) {
213336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        SkImageFilter* input = this->getInput(i);
214336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        if (input) {
215336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            SkRect bounds;
216336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            input->computeFastBounds(src, &bounds);
217336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(bounds);
218336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        } else {
219336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(src);
220336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        }
221336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
222336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org}
223336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2244cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&,
225ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                  SkBitmap*, SkIPoint*) const {
226bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
227bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
228bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
229bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::canFilterImageGPU() const {
230b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return this->asFragmentProcessor(NULL, NULL, SkMatrix::I(), SkIRect());
231bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
232bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
2334cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
234ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                   SkBitmap* result, SkIPoint* offset) const {
235d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
2366aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkBitmap input = src;
237d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(fInputCount == 1);
238aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
2396aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->getInput(0) &&
2404cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
241d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org        return false;
242d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    }
243b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrTexture* srcTexture = input.getTexture();
2444e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkIRect bounds;
245118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
2464e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        return false;
2474e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
2484e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect srcRect = SkRect::Make(bounds);
2494e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
250d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext* context = srcTexture->getContext();
251d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
252d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrTextureDesc desc;
253d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fFlags = kRenderTarget_GrTextureFlagBit,
2544e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fWidth = bounds.width();
2554e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fHeight = bounds.height();
256d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fConfig = kRGBA_8888_GrPixelConfig;
257d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
258d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrAutoScratchTexture dst(context, desc);
259673d9732bf37df724500e04afcdf27d5c711ef60senorblanco    if (NULL == dst.texture()) {
260673d9732bf37df724500e04afcdf27d5c711ef60senorblanco        return false;
261673d9732bf37df724500e04afcdf27d5c711ef60senorblanco    }
262d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoMatrix am;
263d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    am.setIdentity(context);
264d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
2654e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    GrContext::AutoClip acs(context, dstRect);
266b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrFragmentProcessor* fp;
267aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fX = bounds.left();
268aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fY = bounds.top();
269aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    bounds.offset(-srcOffset);
2704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkMatrix matrix(ctx.ctm());
271fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
272b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    this->asFragmentProcessor(&fp, srcTexture, matrix, bounds);
273b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkASSERT(fp);
274d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrPaint paint;
275b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    paint.addColorProcessor(fp)->unref();
2764e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    context->drawRectToRect(paint, dstRect, srcRect);
2774e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
278d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkAutoTUnref<GrTexture> resultTex(dst.detach());
2796aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    WrapTexture(resultTex, bounds.width(), bounds.height(), result);
280d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    return true;
281d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#else
282c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    return false;
283d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
284bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
285bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
286118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
287118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  const SkIPoint& srcOffset, SkIRect* bounds) const {
288118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
289118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
290118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(srcOffset);
291fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkRect cropRect;
292118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
293b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    SkIRect cropRectI;
294b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
2953f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
296118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
297118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
298118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
299118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
300118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!srcBounds.intersect(ctx.clipBounds())) {
301118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
302118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
303118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
304118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    return true;
305118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org}
306118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
307118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
308118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
309118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
310118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
311118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(*srcOffset);
312118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkRect cropRect;
313118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
314118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect cropRectI;
315118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
316118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
317118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
318118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
319118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
320118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
321118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
322118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!bounds->intersect(ctx.clipBounds())) {
323118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
324118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
325118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (srcBounds.contains(*bounds)) {
326118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = src;
327118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
328118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    } else {
329118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
330118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        if (!device) {
331118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org            return false;
332118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        }
333118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkCanvas canvas(device);
334118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.clear(0x00000000);
335118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
336118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
337118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = device->accessBitmap(false);
338118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
339118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
340194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org}
341194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
342bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
343c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                   SkIRect* dst) const {
344c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (fInputCount < 1) {
345c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        return false;
346c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
347c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
348c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkIRect bounds;
349c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    for (int i = 0; i < fInputCount; ++i) {
350c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkImageFilter* filter = this->getInput(i);
351c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkIRect rect = src;
352c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (filter && !filter->filterBounds(src, ctm, &rect)) {
353c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            return false;
354c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
355c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (0 == i) {
356c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds = rect;
357c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        } else {
358c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds.join(rect);
359c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
360c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
361c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
362c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // don't modify dst until now, so we don't accidentally change it in the
363c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // loop, but then return false on the next filter.
364c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    *dst = bounds;
365bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return true;
366bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
367bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
368b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkImageFilter::asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
369b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                        const SkIRect&) const {
370bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
371bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
3728d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
373a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.combool SkImageFilter::asColorFilter(SkColorFilter**) const {
374a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com    return false;
3758d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org}
3766aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3776aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#if SK_SUPPORT_GPU
3786aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3796aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgvoid SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
3806aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
381a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    result->setInfo(info);
3826aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
3836aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3846aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3856aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgbool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy,
3864cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                      const SkBitmap& src, const Context& ctx,
3876aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                                      SkBitmap* result, SkIPoint* offset) const {
3886aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
3896aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // matrix with no clip and that the matrix, clip, and render target set before this function was
3906aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // called are restored before we return to the caller.
3916aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext* context = src.getTexture()->getContext();
3926aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
3936aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->canFilterImageGPU()) {
3944cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        return this->filterImageGPU(proxy, src, ctx, result, offset);
3956aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    } else {
3964cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        if (this->filterImage(proxy, src, ctx, result, offset)) {
3976aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            if (!result->getTexture()) {
398466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                const SkImageInfo info = result->info();
399466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                if (kUnknown_SkColorType == info.colorType()) {
4006aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                    return false;
4016aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                }
4026aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
4036aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
4046aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
4056aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            }
4066aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return true;
4076aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        } else {
4086aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return false;
4096aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        }
4106aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    }
4116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
4126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
413f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
41455b6d8be997a447ef9ce0f029697677a940bfc24senorblanconamespace {
41555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
416be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoclass CacheImpl : public SkImageFilter::Cache {
41755b6d8be997a447ef9ce0f029697677a940bfc24senorblancopublic:
418be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) {
41955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
420be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    virtual ~CacheImpl() {
42155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkTDynamicHash<Value, Key>::Iter iter(&fLookup);
42255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
42355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        while (!iter.done()) {
42455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            Value* v = &*iter;
42555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            ++iter;
42655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            delete v;
42755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
42855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
42955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    struct Value {
43055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset)
43155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            : fKey(key), fBitmap(bitmap), fOffset(offset) {}
43255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Key fKey;
43355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkBitmap fBitmap;
43455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkIPoint fOffset;
43555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        static const Key& GetKey(const Value& v) {
43655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return v.fKey;
43755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
43855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        static uint32_t Hash(const Key& key) {
43955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
44055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
44155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value);
44255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    };
44355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const {
44455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkAutoMutexAcquire mutex(fMutex);
44555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (Value* v = fLookup.find(key)) {
44655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            *result = v->fBitmap;
44755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            *offset = v->fOffset;
44855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (v != fLRU.head()) {
44955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fLRU.remove(v);
45055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                fLRU.addToHead(v);
45155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
45255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            return true;
45355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
45455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        return false;
45555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
45655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) {
45755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        SkAutoMutexAcquire mutex(fMutex);
45855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        if (Value* v = fLookup.find(key)) {
45955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            removeInternal(v);
46055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
46155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        Value* v = new Value(key, result, offset);
46255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLookup.add(v);
46355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLRU.addToHead(v);
46455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fCurrentBytes += result.getSize();
46555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        while (fCurrentBytes > fMaxBytes) {
46655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            Value* tail = fLRU.tail();
46755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkASSERT(tail);
46855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            if (tail == v) {
46955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco                break;
47055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            }
47155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            removeInternal(tail);
47255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        }
47355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
47455b6d8be997a447ef9ce0f029697677a940bfc24senorblancoprivate:
47555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    void removeInternal(Value* v) {
47655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fCurrentBytes -= v->fBitmap.getSize();
47755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLRU.remove(v);
47855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        fLookup.remove(v->fKey);
47955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        delete v;
48055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    }
48155b6d8be997a447ef9ce0f029697677a940bfc24senorblancoprivate:
48255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    SkTDynamicHash<Value, Key>         fLookup;
48355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    mutable SkTInternalLList<Value>    fLRU;
48455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    size_t                             fMaxBytes;
48555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    size_t                             fCurrentBytes;
48655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    mutable SkMutex                    fMutex;
48755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco};
48855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
489be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* CreateCache() {
490be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    return SkImageFilter::Cache::Create(kDefaultCacheSize);
49155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
49255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
49355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco} // namespace
49455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
495be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* SkImageFilter::Cache::Create(size_t maxBytes) {
496be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    return SkNEW_ARGS(CacheImpl, (maxBytes));
49755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
49855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
499be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* SkImageFilter::Cache::Get() {
500be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    SK_DECLARE_STATIC_LAZY_PTR(SkImageFilter::Cache, cache, CreateCache);
50155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    return cache.get();
50255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco}
503