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"
11118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org#include "SkDevice.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
14bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkRect.h"
15f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org#include "SkTDynamicHash.h"
16c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
17d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
18d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#include "GrContext.h"
196aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGrPixelRef.h"
206aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGr.h"
21d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
22bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
231a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgSkImageFilter::Cache* gExternalCache;
241a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
25b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
26194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(inputCount),
27194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[inputCount]),
28b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
298d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < inputCount; ++i) {
309f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        fInputs[i] = inputs[i];
319f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeRef(fInputs[i]);
329f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
339f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
349f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
35b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect)
36194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(1),
37194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[1]),
38b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
39c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[0] = input;
40c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[0]);
41c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org}
42c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org
43b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect)
44194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(2), fInputs(new SkImageFilter*[2]),
45b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
46c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[0] = input1;
47c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[1] = input2;
48c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[0]);
49c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[1]);
509f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
519f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
529f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.orgSkImageFilter::~SkImageFilter() {
538d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
549f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeUnref(fInputs[i]);
559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
569f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    delete[] fInputs;
579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
598b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) {
60ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    fInputCount = buffer.readInt();
61c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    if (buffer.validate((fInputCount >= 0) && ((inputCount < 0) || (fInputCount == inputCount)))) {
62ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = new SkImageFilter*[fInputCount];
63ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        for (int i = 0; i < fInputCount; i++) {
64ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            if (buffer.readBool()) {
65ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                fInputs[i] = buffer.readImageFilter();
66ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            } else {
67ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                fInputs[i] = NULL;
68ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            }
69c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            if (!buffer.isValid()) {
70c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org                fInputCount = i; // Do not use fInputs past that point in the destructor
71c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org                break;
72c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            }
73ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        }
74ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        SkRect rect;
75ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        buffer.readRect(&rect);
76c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org        if (buffer.isValid() && buffer.validate(SkIsValidRect(rect))) {
77ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            uint32_t flags = buffer.readUInt();
78ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            fCropRect = CropRect(rect, flags);
799f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
80ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    } else {
81ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputCount = 0;
82ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = NULL;
839f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
849f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
859f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
868b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkImageFilter::flatten(SkWriteBuffer& buffer) const {
878d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    buffer.writeInt(fInputCount);
888d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
899f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkImageFilter* input = getInput(i);
909f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        buffer.writeBool(input != NULL);
919f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        if (input != NULL) {
929f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org            buffer.writeFlattenable(input);
939f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
949f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
953f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeRect(fCropRect.rect());
963f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeUInt(fCropRect.flags());
979f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
989f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
99bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
1004cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                const Context& context,
101ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const {
102f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    Cache* cache = context.cache();
103bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(result);
1046776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkASSERT(offset);
105f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkASSERT(cache);
106f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (cache->get(this, result, offset)) {
107f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
108f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
109bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    /*
110bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  Give the proxy first shot at the filter. If it returns false, ask
111bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  the filter to do it.
112bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     */
113f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
114f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        this->onFilterImage(proxy, src, context, result, offset)) {
115f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        cache->set(this, *result, *offset);
116f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
117f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
118f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
119bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
120bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
121bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
122c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                 SkIRect* dst) const {
123bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(&src);
124bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(dst);
125bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco    if (SkImageFilter::GetExternalCache()) {
126bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco        /*
127bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco         *  When the external cache is active, do not intersect the saveLayer
128bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco         *  bounds with the clip bounds. This is so that the cached result
129bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco         *  is always the full size of the primitive's bounds,
130bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco         *  regardless of the clip active on first draw.
131bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco         */
132bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco        *dst = SkIRect::MakeLargest();
133bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco        return true;
134bccac6cbf128147587bfc2bc1bdeb46c08175bcasenorblanco    }
135bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return this->onFilterBounds(src, ctm, dst);
136bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
137bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
138336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
139336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (0 == fInputCount) {
140336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
141336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        return;
142336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
143336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getInput(0)) {
144336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getInput(0)->computeFastBounds(src, dst);
145336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    } else {
146336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
147336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
148336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    for (int i = 1; i < fInputCount; i++) {
149336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        SkImageFilter* input = this->getInput(i);
150336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        if (input) {
151336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            SkRect bounds;
152336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            input->computeFastBounds(src, &bounds);
153336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(bounds);
154336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        } else {
155336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(src);
156336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        }
157336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
158336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org}
159336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
1604cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&,
161ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                  SkBitmap*, SkIPoint*) const {
162bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
163bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
164bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
165bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::canFilterImageGPU() const {
1667938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    return this->asNewEffect(NULL, NULL, SkMatrix::I(), SkIRect());
167bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
168bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
1694cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
170ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                   SkBitmap* result, SkIPoint* offset) const {
171d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
1726aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkBitmap input = src;
173d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(fInputCount == 1);
174aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
1756aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->getInput(0) &&
1764cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
177d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org        return false;
178d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    }
179b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrTexture* srcTexture = input.getTexture();
1804e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkIRect bounds;
181118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
1824e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        return false;
1834e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
1844e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect srcRect = SkRect::Make(bounds);
1854e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
186d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext* context = srcTexture->getContext();
187d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
188d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrTextureDesc desc;
189d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fFlags = kRenderTarget_GrTextureFlagBit,
1904e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fWidth = bounds.width();
1914e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fHeight = bounds.height();
192d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fConfig = kRGBA_8888_GrPixelConfig;
193d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
194d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrAutoScratchTexture dst(context, desc);
195d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoMatrix am;
196d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    am.setIdentity(context);
197d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
1984e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    GrContext::AutoClip acs(context, dstRect);
199d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrEffectRef* effect;
200aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fX = bounds.left();
201aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fY = bounds.top();
202aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    bounds.offset(-srcOffset);
2034cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkMatrix matrix(ctx.ctm());
204fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
2057938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    this->asNewEffect(&effect, srcTexture, matrix, bounds);
206d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(effect);
207d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkAutoUnref effectRef(effect);
208d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrPaint paint;
20942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org    paint.addColorEffect(effect);
2104e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    context->drawRectToRect(paint, dstRect, srcRect);
2114e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
212d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkAutoTUnref<GrTexture> resultTex(dst.detach());
2136aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    WrapTexture(resultTex, bounds.width(), bounds.height(), result);
214d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    return true;
215d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#else
216c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    return false;
217d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
218bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
219bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
220118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
221118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  const SkIPoint& srcOffset, SkIRect* bounds) const {
222118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
223118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
224118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(srcOffset);
225fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkRect cropRect;
226118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
227b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    SkIRect cropRectI;
228b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
2293f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
230118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
231118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
232118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
233118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
234118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!srcBounds.intersect(ctx.clipBounds())) {
235118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
236118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
237118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
238118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    return true;
239118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org}
240118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
241118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
242118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
243118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
244118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
245118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(*srcOffset);
246118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkRect cropRect;
247118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
248118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect cropRectI;
249118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
250118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
251118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
252118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
253118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
254118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
255118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
256118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!bounds->intersect(ctx.clipBounds())) {
257118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
258118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
259118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (srcBounds.contains(*bounds)) {
260118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = src;
261118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
262118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    } else {
263118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
264118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        if (!device) {
265118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org            return false;
266118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        }
267118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkCanvas canvas(device);
268118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.clear(0x00000000);
269118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
270118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
271118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = device->accessBitmap(false);
272118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
273118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
274194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org}
275194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
276bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
277c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                   SkIRect* dst) const {
278c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (fInputCount < 1) {
279c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        return false;
280c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
281c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
282c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkIRect bounds;
283c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    for (int i = 0; i < fInputCount; ++i) {
284c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkImageFilter* filter = this->getInput(i);
285c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkIRect rect = src;
286c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (filter && !filter->filterBounds(src, ctm, &rect)) {
287c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            return false;
288c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
289c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (0 == i) {
290c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds = rect;
291c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        } else {
292c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds.join(rect);
293c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
294c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
295c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
296c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // don't modify dst until now, so we don't accidentally change it in the
297c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // loop, but then return false on the next filter.
298c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    *dst = bounds;
299bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return true;
300bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
301bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
3027938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgbool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&, const SkIRect&) const {
303bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
304bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
3058d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
306a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.combool SkImageFilter::asColorFilter(SkColorFilter**) const {
307a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com    return false;
3088d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org}
3096aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3101a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgvoid SkImageFilter::SetExternalCache(Cache* cache) {
3111a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    SkRefCnt_SafeAssign(gExternalCache, cache);
3121a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
3131a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
3141a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgSkImageFilter::Cache* SkImageFilter::GetExternalCache() {
3151a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    return gExternalCache;
3161a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
3171a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
3186aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#if SK_SUPPORT_GPU
3196aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3206aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgvoid SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
3216aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
322a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    result->setInfo(info);
3236aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
3246aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3256aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3266aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgbool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy,
3274cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                      const SkBitmap& src, const Context& ctx,
3286aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                                      SkBitmap* result, SkIPoint* offset) const {
3296aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
3306aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // matrix with no clip and that the matrix, clip, and render target set before this function was
3316aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // called are restored before we return to the caller.
3326aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext* context = src.getTexture()->getContext();
3336aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
3346aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->canFilterImageGPU()) {
3354cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        return this->filterImageGPU(proxy, src, ctx, result, offset);
3366aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    } else {
3374cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        if (this->filterImage(proxy, src, ctx, result, offset)) {
3386aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            if (!result->getTexture()) {
339466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                const SkImageInfo info = result->info();
340466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                if (kUnknown_SkColorType == info.colorType()) {
3416aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                    return false;
3426aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                }
3436aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
3446aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
3456aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
3466aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            }
3476aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return true;
3486aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        } else {
3496aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return false;
3506aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        }
3516aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    }
3526aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3536aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
354f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
355f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgstatic uint32_t compute_hash(const uint32_t* data, int count) {
356f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    uint32_t hash = 0;
357f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
358f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    for (int i = 0; i < count; ++i) {
359f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        uint32_t k = data[i];
360f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k *= 0xcc9e2d51;
361f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k = (k << 15) | (k >> 17);
362f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k *= 0x1b873593;
363f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
364f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash ^= k;
365f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash = (hash << 13) | (hash >> 19);
366f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash *= 5;
367f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash += 0xe6546b64;
368f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
369f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
370f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    //    hash ^= size;
371f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 16;
372f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash *= 0x85ebca6b;
373f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 13;
374f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash *= 0xc2b2ae35;
375f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 16;
376f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
377f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return hash;
378f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
379f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
380f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgclass CacheImpl : public SkImageFilter::Cache {
381f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgpublic:
382f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {}
383f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    virtual ~CacheImpl();
384f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
385f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE;
3861a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    void remove(const SkImageFilter* key) SK_OVERRIDE;
387f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgprivate:
388f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    typedef const SkImageFilter* Key;
389f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    struct Value {
390f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Value(Key key, const SkBitmap& bitmap, const SkIPoint& offset)
391f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            : fKey(key), fBitmap(bitmap), fOffset(offset) {}
392f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Key fKey;
393f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkBitmap fBitmap;
394f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkIPoint fOffset;
395f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        static const Key& GetKey(const Value& v) {
396f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            return v.fKey;
397f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        }
398f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        static uint32_t Hash(Key key) {
399f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            return compute_hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key) / sizeof(uint32_t));
400f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        }
401f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    };
402f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkTDynamicHash<Value, Key> fData;
403f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    int fMinChildren;
404f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org};
405f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
406f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgbool CacheImpl::get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) {
407f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    Value* v = fData.find(key);
408f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (v) {
409f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        *result = v->fBitmap;
410f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        *offset = v->fOffset;
411f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
412f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
413f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
414f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
415f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
4161a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgvoid CacheImpl::remove(const SkImageFilter* key) {
4171a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    Value* v = fData.find(key);
4181a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    if (v) {
4191a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org        fData.remove(key);
4201a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org        delete v;
4211a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    }
4221a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
4231a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
424f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgvoid CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) {
425f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (key->getRefCnt() >= fMinChildren) {
426f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        fData.add(new Value(key, result, offset));
427f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
428f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
429f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
430f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgSkImageFilter::Cache* SkImageFilter::Cache::Create(int minChildren) {
431f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return new CacheImpl(minChildren);
432f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
433f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
434f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgCacheImpl::~CacheImpl() {
435f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkTDynamicHash<Value, Key>::Iter iter(&fData);
436f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
437f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    while (!iter.done()) {
438f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Value* v = &*iter;
439f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        ++iter;
440f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        delete v;
441f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
442f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
443