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