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