160014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org/* 260014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org * Copyright 2011 The Android Open Source Project 360014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org * 460014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 560014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org * found in the LICENSE file. 660014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org */ 760014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org 864a0ec36555352ec31aa7c5a7630a5d042b010badjsollen@google.com#include "SkBitmap.h" 960014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org#include "SkBlurImageFilter.h" 10ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org#include "SkColorPriv.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 13736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkGpuBlurUtils.h" 1427eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org#include "SkBlurImage_opts.h" 15cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 16302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org#include "GrContext.h" 17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 1860014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org 1909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org// This rather arbitrary-looking value results in a maximum box blur kernel size 2009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org// of 1000 pixels on the raster path, which matches the WebKit and Firefox 2109843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org// implementations. Since the GPU path does not compute a box blur, putting 2209843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org// the limit on sigma ensures consistent behaviour between the GPU and 2309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org// raster paths. 2409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org#define MAX_SIGMA SkIntToScalar(532) 2509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org 2632673b99a4fb5d798206eb7665b730ed0b4597a0senorblancostatic SkVector mapSigma(const SkSize& localSigma, const SkMatrix& ctm) { 2732673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco SkVector sigma = SkVector::Make(localSigma.width(), localSigma.height()); 2832673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco ctm.mapVectors(&sigma, 1); 2932673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco sigma.fX = SkMinScalar(SkScalarAbs(sigma.fX), MAX_SIGMA); 3032673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco sigma.fY = SkMinScalar(SkScalarAbs(sigma.fY), MAX_SIGMA); 3132673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco return sigma; 3232673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco} 3332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco 349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 358b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkBlurImageFilter::SkBlurImageFilter(SkReadBuffer& buffer) 36ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org : INHERITED(1, buffer) { 3754e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org fSigma.fWidth = buffer.readScalar(); 3854e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org fSigma.fHeight = buffer.readScalar(); 39c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org buffer.validate(SkScalarIsFinite(fSigma.fWidth) && 40c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org SkScalarIsFinite(fSigma.fHeight) && 41c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org (fSigma.fWidth >= 0) && 42c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org (fSigma.fHeight >= 0)); 4354e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org} 449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 4554e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org 46194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.orgSkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, 47194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org SkScalar sigmaY, 48194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org SkImageFilter* input, 495e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco const CropRect* cropRect, 505e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco uint32_t uniqueID) 515e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco : INHERITED(1, &input, cropRect, uniqueID), fSigma(SkSize::Make(sigmaX, sigmaY)) { 5260014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org} 5360014ca38710d3fc265f4376b05c0fefd0e044cfsenorblanco@chromium.org 549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkBlurImageFilter::CreateProc(SkReadBuffer& buffer) { 559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar sigmaX = buffer.readScalar(); 579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar sigmaY = buffer.readScalar(); 585e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco return Create(sigmaX, sigmaY, common.getInput(0), &common.cropRect(), common.uniqueID()); 599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkBlurImageFilter::flatten(SkWriteBuffer& buffer) const { 6254e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org this->INHERITED::flatten(buffer); 6354e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org buffer.writeScalar(fSigma.fWidth); 6454e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org buffer.writeScalar(fSigma.fHeight); 6554e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org} 6654e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org 670cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.orgenum BlurDirection { 680cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org kX, kY 690cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org}; 700cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org 710cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org/** 720cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * 730cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * In order to make memory accesses cache-friendly, we reorder the passes to 740cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * use contiguous memory reads wherever possible. 750cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * 760cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * For example, the 6 passes of the X-and-Y blur case are rewritten as 770cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * follows. Instead of 3 passes in X and 3 passes in Y, we perform 780cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X, 790cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * then 1 pass in X transposed to Y on write. 800cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * 810cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * +----+ +----+ +----+ +---+ +---+ +---+ +----+ 820cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | -----> | AB | 830cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blurXY +----+ 840cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * +---+ +---+ +---+ 850cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * 860cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * In this way, two of the y-blurs become x-blurs applied to transposed 870cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org * images, and all memory reads are contiguous. 880cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org */ 890cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org 900cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.orgtemplate<BlurDirection srcDirection, BlurDirection dstDirection> 910cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.orgstatic void boxBlur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSize, 920cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int leftOffset, int rightOffset, int width, int height) 93ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org{ 94ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org int rightBorder = SkMin32(rightOffset + 1, width); 950cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int srcStrideX = srcDirection == kX ? 1 : srcStride; 960cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int dstStrideX = dstDirection == kX ? 1 : height; 970cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int srcStrideY = srcDirection == kX ? srcStride : 1; 980cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int dstStrideY = dstDirection == kX ? width : 1; 99fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org uint32_t scale = (1 << 24) / kernelSize; 100fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org uint32_t half = 1 << 23; 101ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org for (int y = 0; y < height; ++y) { 102ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org int sumA = 0, sumR = 0, sumG = 0, sumB = 0; 1030cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org const SkPMColor* p = src; 104ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org for (int i = 0; i < rightBorder; ++i) { 105ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumA += SkGetPackedA32(*p); 106ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumR += SkGetPackedR32(*p); 107ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumG += SkGetPackedG32(*p); 108ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumB += SkGetPackedB32(*p); 1090cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org p += srcStrideX; 110ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 111ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 1120cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org const SkPMColor* sptr = src; 1130cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SkColor* dptr = dst; 114ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org for (int x = 0; x < width; ++x) { 115fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org *dptr = SkPackARGB32((sumA * scale + half) >> 24, 116fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org (sumR * scale + half) >> 24, 117fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org (sumG * scale + half) >> 24, 118fe2faa8b16e2a607543c5b30637e7da54012e169senorblanco@chromium.org (sumB * scale + half) >> 24); 119ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (x >= leftOffset) { 1200cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SkColor l = *(sptr - leftOffset * srcStrideX); 121ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumA -= SkGetPackedA32(l); 122ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumR -= SkGetPackedR32(l); 123ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumG -= SkGetPackedG32(l); 124ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumB -= SkGetPackedB32(l); 125ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 126ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (x + rightOffset + 1 < width) { 1270cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SkColor r = *(sptr + (rightOffset + 1) * srcStrideX); 128ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumA += SkGetPackedA32(r); 129ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumR += SkGetPackedR32(r); 130ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumG += SkGetPackedG32(r); 131ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org sumB += SkGetPackedB32(r); 132ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 1330cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org sptr += srcStrideX; 1340cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org if (srcDirection == kY) { 1350cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SK_PREFETCH(sptr + (rightOffset + 1) * srcStrideX); 1360cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org } 1370cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org dptr += dstStrideX; 138ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 1390cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org src += srcStrideY; 1400cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org dst += dstStrideY; 141ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 142ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org} 143ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 1447b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.orgstatic void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset, 1457b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org int *highOffset) 146ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org{ 14773f3dedf597757bd3e7036b657eeb790fb5a1fb9schenney@chromium.org float pi = SkScalarToFloat(SK_ScalarPI); 14873f3dedf597757bd3e7036b657eeb790fb5a1fb9schenney@chromium.org int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f)); 149ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *kernelSize = d; 150ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (d % 2 == 1) { 151ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *lowOffset = *highOffset = (d - 1) / 2; 152ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *kernelSize3 = d; 153ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } else { 154ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *highOffset = d / 2; 155ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *lowOffset = *highOffset - 1; 156ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org *kernelSize3 = d + 1; 157ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 158ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org} 159ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 160f1369ce607adf55ffffe58fb93893bafb6ff6ebesenorblanco@chromium.orgbool SkBlurImageFilter::onFilterImage(Proxy* proxy, 1614cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const SkBitmap& source, const Context& ctx, 162ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkBitmap* dst, SkIPoint* offset) const { 16368400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org SkBitmap src = source; 1646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkIPoint srcOffset = SkIPoint::Make(0, 0); 1654cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) { 16668400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org return false; 16768400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org } 16868400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.org 16928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org if (src.colorType() != kN32_SkColorType) { 170ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org return false; 171ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 172ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 173118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org SkIRect srcBounds, dstBounds; 174118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) { 17576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com return false; 17676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 17776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com 178118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org SkAutoLockPixels alp(src); 179118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!src.getPixels()) { 180194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org return false; 181194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org } 182194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org 183848250415eddc54075f7eb8795e8db79e749c6abreed if (!dst->tryAllocPixels(src.info().makeWH(srcBounds.width(), srcBounds.height()))) { 184cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 185cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 186c77392ed58ec78ab19fa0e3ff99fb8110854fba2reed dst->getBounds(&dstBounds); 187cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org 18832673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco SkVector sigma = mapSigma(fSigma, ctx.ctm()); 1892bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org 190ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; 191ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; 1922bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX); 1932bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY); 194ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 195ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (kernelSizeX < 0 || kernelSizeY < 0) { 196ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org return false; 197ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 198ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 199ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (kernelSizeX == 0 && kernelSizeY == 0) { 2008a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org src.copyTo(dst, dst->colorType()); 2016776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = srcBounds.fLeft; 2026776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = srcBounds.fTop; 203ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org return true; 204ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 205ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 206ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org SkBitmap temp; 207848250415eddc54075f7eb8795e8db79e749c6abreed if (!temp.tryAllocPixels(dst->info())) { 208ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org return false; 209ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 210ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 2116776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = srcBounds.fLeft; 2126776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = srcBounds.fTop; 2136776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org srcBounds.offset(-srcOffset); 2140cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top()); 2150cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SkPMColor* t = temp.getAddr32(0, 0); 2160cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org SkPMColor* d = dst->getAddr32(0, 0); 2170cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int w = dstBounds.width(), h = dstBounds.height(); 2180cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org int sw = src.rowBytesAsPixels(); 21905edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org SkBoxBlurProc boxBlurX, boxBlurY, boxBlurXY, boxBlurYX; 22005edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org if (!SkBoxBlurGetPlatformProcs(&boxBlurX, &boxBlurY, &boxBlurXY, &boxBlurYX)) { 22127eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org boxBlurX = boxBlur<kX, kX>; 22227eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org boxBlurY = boxBlur<kY, kY>; 22327eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org boxBlurXY = boxBlur<kX, kY>; 22405edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org boxBlurYX = boxBlur<kY, kX>; 22527eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org } 22627eec46d6925afc76c2241c6b3182ce9b3284c9esenorblanco@chromium.org 227ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org if (kernelSizeX > 0 && kernelSizeY > 0) { 2280cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w, h); 2290cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w, h); 2300cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurXY(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w, h); 2310cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); 2320cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); 2330cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); 234ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } else if (kernelSizeX > 0) { 2350cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w, h); 2360cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w, h); 2370cc00c273dcad0fb073df32b38e89d15064ebb0esenorblanco@chromium.org boxBlurX(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w, h); 238ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } else if (kernelSizeY > 0) { 23905edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org boxBlurYX(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); 24005edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); 24105edd02a7c3d78fe11bbaec83aaa63b2823cce42senorblanco@chromium.org boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); 242ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org } 243ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org return true; 244ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org} 245ae814c74763e3f7c13aeb03f6f8b894bd11ff35esenorblanco@chromium.org 246336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 247336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 248336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org if (getInput(0)) { 249336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org getInput(0)->computeFastBounds(src, dst); 250336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org } else { 251336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org *dst = src; 252336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org } 253336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 254336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org dst->outset(SkScalarMul(fSigma.width(), SkIntToScalar(3)), 255336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org SkScalarMul(fSigma.height(), SkIntToScalar(3))); 256336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org} 257c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org 258c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.orgbool SkBlurImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 259c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkIRect* dst) const { 260c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkIRect bounds = src; 26132673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco SkVector sigma = mapSigma(fSigma, ctm); 262c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), 263c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); 2641150a6d151571fb6ee816dadec844ae7ab53948asenorblanco if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { 2651150a6d151571fb6ee816dadec844ae7ab53948asenorblanco return false; 2661150a6d151571fb6ee816dadec844ae7ab53948asenorblanco } 267c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org *dst = bounds; 268c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org return true; 269c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org} 270c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org 2714cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, 272ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkBitmap* result, SkIPoint* offset) const { 273cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 2746aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org SkBitmap input = src; 275aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org SkIPoint srcOffset = SkIPoint::Make(0, 0); 2764cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) { 277c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org return false; 278c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org } 279194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org SkIRect rect; 280118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) { 281194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org return false; 282194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org } 283118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org GrTexture* source = input.getTexture(); 28432673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco SkVector sigma = mapSigma(fSigma, ctx.ctm()); 285aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org offset->fX = rect.fLeft; 286aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org offset->fY = rect.fTop; 287aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org rect.offset(-srcOffset); 2886ae6383f56704928838032ce6c46829e06201853skia.committer@gmail.com SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(), 289194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org source, 290194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org false, 291194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org SkRect::Make(rect), 292194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org true, 2932bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org sigma.x(), 2942bfe36b68d11d05c114a33d62f9f45427e316916senorblanco@chromium.org sigma.y())); 2956aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org WrapTexture(tex, rect.width(), rect.height(), result); 2966aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org return true; 297cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 298cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 299c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org return false; 300cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 301302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org} 302