1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMaskFilter.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMask.h" 10736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkGpuBlurUtils.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 14a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 157c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com#include "SkRTConf.h" 160bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#include "SkStringUtils.h" 17491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkStrokeRec.h" 18491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 19491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 2030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips#include "GrCircleBlurFragmentProcessor.h" 21491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "GrContext.h" 22ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips#include "GrDrawContext.h" 23491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "GrTexture.h" 246251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#include "GrFragmentProcessor.h" 25605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h" 263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org#include "SkDraw.h" 27eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "effects/GrSimpleTextureEffect.h" 2864c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 292d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 30018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 317dc4bd06fca73a97dcf3ad4a7425597160f1edfcegdaniel#include "glsl/GrGLSLTextureSampler.h" 327ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 33491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.orgSkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { 36508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org return SkBlurMask::ConvertRadiusToSigma(radius); 37508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org} 38508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkBlurMaskFilterImpl : public SkMaskFilter { 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 41e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overrides from SkMaskFilter 4436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkMask::Format getFormat() const override; 45ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, 46ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkIPoint* margin) const override; 472e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 48491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 4930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips bool canFilterMaskGPU(const SkRRect& devRRect, 50ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 51ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& ctm, 52ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkRect* maskRect) const override; 53ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool directFilterMaskGPU(GrTextureProvider* texProvider, 54ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrDrawContext* drawContext, 55ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrPaint* grp, 56ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const GrClip&, 57ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& viewMatrix, 58ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkStrokeRec& strokeRec, 59ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkPath& path) const override; 60ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool directFilterRRectMaskGPU(GrTextureProvider* texProvider, 61ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrDrawContext* drawContext, 62ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrPaint* grp, 63ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const GrClip&, 64ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& viewMatrix, 65ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkStrokeRec& strokeRec, 66ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkRRect& rrect) const override; 67ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool filterMaskGPU(GrTexture* src, 68ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& ctm, 69ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkRect& maskRect, 70ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrTexture** result, 71ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool canOverwriteSrc) const override; 72491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif 73491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 7436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void computeFastBounds(const SkRect&, SkRect*) const override; 7536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool asABlur(BlurRec*) const override; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 770f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 78ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 80d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comprotected: 81ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&, 82ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 83ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips NinePatch*) const override; 842e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 85ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, 86ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 87ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips NinePatch*) const override; 88a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 892e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, 907c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkIPoint* margin, SkMask::CreateMode createMode) const; 91a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix, 92a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkIPoint* margin, SkMask::CreateMode createMode) const; 93453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 95491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // To avoid unseemly allocation requests (esp. for finite platforms like 96491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // handset) we limit the radius so something manageable. (as opposed to 97491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // a request like 10,000) 987ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com static const SkScalar kMAX_BLUR_SIGMA; 997ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 100e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkScalar fSigma; 101e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkBlurStyle fBlurStyle; 102e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org uint32_t fBlurFlags; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 104daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkBlurQuality getQuality() const { 105daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? 106daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com kHigh_SkBlurQuality : kLow_SkBlurQuality; 107daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 108daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 1098b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkBlurMaskFilterImpl(SkReadBuffer&); 11036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void flatten(SkWriteBuffer&) const override; 1117ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 1127ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar computeXformedSigma(const SkMatrix& ctm) const { 113491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag); 114491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1157ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma); 1167ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); 117491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 118fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed friend class SkBlurMaskFilter; 1209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkMaskFilter INHERITED; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1247ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.comconst SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); 125491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 126e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.orgSkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32_t flags) { 127e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (!SkScalarIsFinite(sigma) || sigma <= 0) { 12896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 12903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com } 130e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { 13196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 132e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } 133e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (flags > SkBlurMaskFilter::kAll_BlurFlag) { 13496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 135e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } 136385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new SkBlurMaskFilterImpl(sigma, style, flags); 137e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org} 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com/////////////////////////////////////////////////////////////////////////////// 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 141e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.orgSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, uint32_t flags) 142e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org : fSigma(sigma) 143e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org , fBlurStyle(style) 144e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org , fBlurFlags(flags) { 145e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkASSERT(fSigma > 0); 146e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle); 147038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15030711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comSkMask::Format SkBlurMaskFilterImpl::getFormat() const { 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkMask::kA8_Format; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 154daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const { 155daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { 156daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return false; 157daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 158daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 159daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (rec) { 160daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fSigma = fSigma; 161daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fStyle = fBlurStyle; 162daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fQuality = this->getQuality(); 163daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 164daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return true; 165daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 166daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 16703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.combool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, 16830711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMatrix& matrix, 16930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin) const { 1707ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar sigma = this->computeXformedSigma(matrix); 171daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin); 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1747c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.combool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, 1757c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com const SkMatrix& matrix, 17630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin, SkMask::CreateMode createMode) const { 1777ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar sigma = computeXformedSigma(matrix); 1787c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 17930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle, margin, createMode); 1807c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com} 1817c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 182a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.orgbool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r, 183a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org const SkMatrix& matrix, 18430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin, SkMask::CreateMode createMode) const { 185a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkScalar sigma = computeXformedSigma(matrix); 186a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 18730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle, margin, createMode); 188a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org} 189a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 190d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#include "SkCanvas.h" 191d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 192a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { 19396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(mask != nullptr); 194a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 195b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed mask->fBounds = bounds.roundOut(); 196d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com mask->fRowBytes = SkAlign4(mask->fBounds.width()); 197d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com mask->fFormat = SkMask::kA8_Format; 198a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const size_t size = mask->computeImageSize(); 199d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com mask->fImage = SkMask::AllocImage(size); 20096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == mask->fImage) { 201d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return false; 202d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 203a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 204a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // FIXME: use sk_calloc in AllocImage? 205d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com sk_bzero(mask->fImage, size); 206a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return true; 207a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 208a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 209a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) { 210a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (!prepare_to_draw_into_mask(rrect.rect(), mask)) { 211a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return false; 212a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 213a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 214a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a 215a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // clean way to share more code? 216a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkBitmap bitmap; 217dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org bitmap.installMaskPixels(*mask); 218a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 219a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkCanvas canvas(bitmap); 220a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 221a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com -SkIntToScalar(mask->fBounds.top())); 222a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 223a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPaint paint; 224a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com paint.setAntiAlias(true); 225a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com canvas.drawRRect(rrect, paint); 226a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return true; 227a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 228a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 229a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask) { 230a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (!prepare_to_draw_into_mask(rects[0], mask)) { 231a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return false; 232a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 233d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 234d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkBitmap bitmap; 235e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org bitmap.installPixels(SkImageInfo::Make(mask->fBounds.width(), 236e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org mask->fBounds.height(), 237e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org kAlpha_8_SkColorType, 238e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org kPremul_SkAlphaType), 23900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org mask->fImage, mask->fRowBytes); 240d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 241d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkCanvas canvas(bitmap); 242dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 243dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com -SkIntToScalar(mask->fBounds.top())); 244d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 245d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkPaint paint; 246d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com paint.setAntiAlias(true); 247d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 248dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (1 == count) { 249dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.drawRect(rects[0], paint); 250dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } else { 251dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // todo: do I need a fast way to do this? 252dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkPath path; 253dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.addRect(rects[0]); 254dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.addRect(rects[1]); 255dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.setFillType(SkPath::kEvenOdd_FillType); 256dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.drawPath(path, paint); 257dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 258d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return true; 259d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com} 260d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 261f276fa74f56d0c691716163d3149fce5de97c9eareed@google.comstatic bool rect_exceeds(const SkRect& r, SkScalar v) { 262f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || 263f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com r.width() > v || r.height() > v; 26407784a041925f9a921e390e782195a622c76fbfareed@google.com} 26507784a041925f9a921e390e782195a622c76fbfareed@google.com 266eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao#include "SkMaskCache.h" 267eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 268b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* copy_mask_to_cacheddata(SkMask* mask) { 269b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed const size_t size = mask->computeTotalImageSize(); 270eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao SkCachedData* data = SkResourceCache::NewCachedData(size); 271eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao if (data) { 272b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed memcpy(data->writable_data(), mask->fImage, size); 273b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMask::FreeImage(mask->fImage); 274b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed mask->fImage = (uint8_t*)data->data(); 275eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 276b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return data; 277eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 278eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 279b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* find_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, 280b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRRect& rrect) { 281b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return SkMaskCache::FindAndRef(sigma, style, quality, rrect, mask); 282eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 283eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 284b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* add_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, 285b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRRect& rrect) { 286b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = copy_mask_to_cacheddata(mask); 287b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (cache) { 288b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMaskCache::Add(sigma, style, quality, rrect, *mask, cache); 289eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 290b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return cache; 291eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 292eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 293b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* find_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, 294b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRect rects[], int count) { 295b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return SkMaskCache::FindAndRef(sigma, style, quality, rects, count, mask); 296eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 297eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 298b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* add_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, 299b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRect rects[], int count) { 300b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = copy_mask_to_cacheddata(mask); 301b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (cache) { 302b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMaskCache::Add(sigma, style, quality, rects, count, *mask, cache); 303eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 304b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return cache; 305eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 306eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 307a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#ifdef SK_IGNORE_FAST_RRECT_BLUR 308a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholasSK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects"); 309a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#else 310a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholasSK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects"); 311a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#endif 312a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 313a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::FilterReturn 314a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix, 315a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkIRect& clipBounds, 316a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com NinePatch* patch) const { 31796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(patch != nullptr); 318a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com switch (rrect.getType()) { 319a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kEmpty_Type: 320a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Nothing to draw. 321a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kFalse_FilterReturn; 322a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 323a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kRect_Type: 324a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // We should have caught this earlier. 325a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkASSERT(false); 326a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Fall through. 327a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kOval_Type: 328a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // The nine patch special case does not handle ovals, and we 329a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // already have code for rectangles. 330a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 331a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 332f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org // These three can take advantage of this fast path. 333a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kSimple_Type: 334f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org case SkRRect::kNinePatch_Type: 335a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kComplex_Type: 336a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com break; 337a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 338a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 339a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 340a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // total bounds, but we do need an inset the size of our blur-radius 341e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle) { 342a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 343a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 344a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 345a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: take clipBounds into account to limit our coordinates up front 346a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // for now, just skip too-large src rects (to take the old code path). 347a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rect_exceeds(rrect.rect(), SkIntToScalar(32767))) { 348a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 349a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 350a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 351a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkIPoint margin; 352a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkMask srcM, dstM; 353b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed srcM.fBounds = rrect.rect().roundOut(); 354a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com srcM.fFormat = SkMask::kA8_Format; 355a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com srcM.fRowBytes = 0; 356a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 357a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org bool filterResult = false; 358a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (c_analyticBlurRRect) { 359a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org // special case for fast round rect blur 360a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org // don't actually do the blur the first time, just compute the correct size 361a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin, 362a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkMask::kJustComputeBounds_CreateMode); 363a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 364a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 365a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (!filterResult) { 366a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org filterResult = this->filterMask(&dstM, srcM, matrix, &margin); 367a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 368a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 369a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (!filterResult) { 370a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kFalse_FilterReturn; 371a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 372a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 373a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now figure out the appropriate width and height of the smaller round rectangle 374a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // to stretch. It will take into account the larger radius per side as well as double 375a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // the margin, to account for inner and outer blur. 376a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner); 377a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner); 378a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner); 379a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner); 380a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 381a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar leftUnstretched = SkTMax(UL.fX, LL.fX) + SkIntToScalar(2 * margin.fX); 382a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar rightUnstretched = SkTMax(UR.fX, LR.fX) + SkIntToScalar(2 * margin.fX); 383a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 384a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Extra space in the middle to ensure an unchanging piece for stretching. Use 3 to cover 385a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // any fractional space on either side plus 1 for the part to stretch. 386a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar stretchSize = SkIntToScalar(3); 387a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 388a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar totalSmallWidth = leftUnstretched + rightUnstretched + stretchSize; 389a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (totalSmallWidth >= rrect.rect().width()) { 390a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // There is no valid piece to stretch. 391a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 392a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 393a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 394a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar topUnstretched = SkTMax(UL.fY, UR.fY) + SkIntToScalar(2 * margin.fY); 395a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar bottomUnstretched = SkTMax(LL.fY, LR.fY) + SkIntToScalar(2 * margin.fY); 396a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 397a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar totalSmallHeight = topUnstretched + bottomUnstretched + stretchSize; 398a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (totalSmallHeight >= rrect.rect().height()) { 399a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // There is no valid piece to stretch. 400a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 401a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 402a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 403a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); 404a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 405a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect smallRR; 406a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkVector radii[4]; 407a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kUpperLeft_Corner] = UL; 408a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kUpperRight_Corner] = UR; 409a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kLowerRight_Corner] = LR; 410a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kLowerLeft_Corner] = LL; 411a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com smallRR.setRectRadii(smallR, radii); 412a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 4134dca7a829635b552be369186ff508a94aba6a903reed const SkScalar sigma = this->computeXformedSigma(matrix); 414b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = find_cached_rrect(&patch->fMask, sigma, fBlurStyle, 415b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed this->getQuality(), smallRR); 416b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (!cache) { 4174dca7a829635b552be369186ff508a94aba6a903reed bool analyticBlurWorked = false; 4184dca7a829635b552be369186ff508a94aba6a903reed if (c_analyticBlurRRect) { 4194dca7a829635b552be369186ff508a94aba6a903reed analyticBlurWorked = 4204dca7a829635b552be369186ff508a94aba6a903reed this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, 4214dca7a829635b552be369186ff508a94aba6a903reed SkMask::kComputeBoundsAndRenderImage_CreateMode); 422a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 423ad99358bdd7ca4ffb047121946abf0d5fdbde1e8robertphillips@google.com 4244dca7a829635b552be369186ff508a94aba6a903reed if (!analyticBlurWorked) { 4254dca7a829635b552be369186ff508a94aba6a903reed if (!draw_rrect_into_mask(smallRR, &srcM)) { 4264dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 4274dca7a829635b552be369186ff508a94aba6a903reed } 428a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 4294dca7a829635b552be369186ff508a94aba6a903reed SkAutoMaskFreeImage amf(srcM.fImage); 4304dca7a829635b552be369186ff508a94aba6a903reed 4314dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 4324dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 4334dca7a829635b552be369186ff508a94aba6a903reed } 434a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 435b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed cache = add_cached_rrect(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR); 436a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 437a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 438a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fMask.fBounds.offsetTo(0, 0); 439a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fOuterRect = dstM.fBounds; 440a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; 441a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; 44296fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == patch->fCache); 443b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed patch->fCache = cache; // transfer ownership to patch 444a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kTrue_FilterReturn; 445a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 446a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 447a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholasSK_CONF_DECLARE(bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects"); 4487c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 449d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comSkMaskFilter::FilterReturn 450dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comSkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, 451dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkMatrix& matrix, 452dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkIRect& clipBounds, 45330711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com NinePatch* patch) const { 454dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (count < 1 || count > 2) { 455dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com return kUnimplemented_FilterReturn; 456dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 4573458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com 45857850b9daddd941f880d94faaf83f2169355a0c8reed@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 45957850b9daddd941f880d94faaf83f2169355a0c8reed@google.com // total bounds, but we do need an inset the size of our blur-radius 460e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle || kOuter_SkBlurStyle == fBlurStyle) { 46157850b9daddd941f880d94faaf83f2169355a0c8reed@google.com return kUnimplemented_FilterReturn; 46257850b9daddd941f880d94faaf83f2169355a0c8reed@google.com } 46357850b9daddd941f880d94faaf83f2169355a0c8reed@google.com 46407784a041925f9a921e390e782195a622c76fbfareed@google.com // TODO: take clipBounds into account to limit our coordinates up front 46507784a041925f9a921e390e782195a622c76fbfareed@google.com // for now, just skip too-large src rects (to take the old code path). 466f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com if (rect_exceeds(rects[0], SkIntToScalar(32767))) { 46707784a041925f9a921e390e782195a622c76fbfareed@google.com return kUnimplemented_FilterReturn; 46807784a041925f9a921e390e782195a622c76fbfareed@google.com } 4693458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com 470d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkIPoint margin; 471d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkMask srcM, dstM; 472b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed srcM.fBounds = rects[0].roundOut(); 473d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com srcM.fFormat = SkMask::kA8_Format; 474d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com srcM.fRowBytes = 0; 4752e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 4767c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com bool filterResult = false; 4777c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (count == 1 && c_analyticBlurNinepatch) { 4787c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com // special case for fast rect blur 4797c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com // don't actually do the blur the first time, just compute the correct size 4802e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, 4817c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkMask::kJustComputeBounds_CreateMode); 4827c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } else { 4837c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com filterResult = this->filterMask(&dstM, srcM, matrix, &margin); 4847c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 4852e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 4867c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (!filterResult) { 487d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return kFalse_FilterReturn; 488d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 489d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 490d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com /* 491d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * smallR is the smallest version of 'rect' that will still guarantee that 492d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * we get the same blur results on all edges, plus 1 center row/col that is 493d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * representative of the extendible/stretchable edges of the ninepatch. 494d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * Since our actual edge may be fractional we inset 1 more to be sure we 495d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * don't miss any interior blur. 496d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * x is an added pixel of blur, and { and } are the (fractional) edge 497d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * pixels from the original rect. 498d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * 499d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * x x { x x .... x x } x x 500d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * 501d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * Thus, in this case, we inset by a total of 5 (on each side) beginning 502d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * with our outer-rect (dstM.fBounds) 503d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com */ 504dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkRect smallR[2]; 505dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkIPoint center; 506dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 507dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // +2 is from +1 for each edge (to account for possible fractional edges 508dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2; 509dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2; 510dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkIRect innerIR; 511dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 512dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (1 == count) { 513dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com innerIR = srcM.fBounds; 514dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com center.set(smallW, smallH); 515dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } else { 516dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkASSERT(2 == count); 517dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com rects[1].roundIn(&innerIR); 518dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com center.set(smallW + (innerIR.left() - srcM.fBounds.left()), 519dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallH + (innerIR.top() - srcM.fBounds.top())); 520dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 521dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 522dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // +1 so we get a clean, stretchable, center row/col 523dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallW += 1; 524dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallH += 1; 525dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 526dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // we want the inset amounts to be integral, so we don't change any 527dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // fractional phase on the fRight or fBottom of our smallR. 528dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); 529dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); 530dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (dx < 0 || dy < 0) { 531dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // we're too small, relative to our blur, to break into nine-patch, 532dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // so we ask to have our normal filterMask() be called. 533dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com return kUnimplemented_FilterReturn; 534dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 535dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 536dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy); 537112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com if (smallR[0].width() < 2 || smallR[0].height() < 2) { 538112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com return kUnimplemented_FilterReturn; 539112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com } 540dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (2 == count) { 541dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallR[1].set(rects[1].left(), rects[1].top(), 542dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com rects[1].right() - dx, rects[1].bottom() - dy); 543dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkASSERT(!smallR[1].isEmpty()); 544d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 545d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 5464dca7a829635b552be369186ff508a94aba6a903reed const SkScalar sigma = this->computeXformedSigma(matrix); 547b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = find_cached_rects(&patch->fMask, sigma, fBlurStyle, 548b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed this->getQuality(), smallR, count); 549b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (!cache) { 5504dca7a829635b552be369186ff508a94aba6a903reed if (count > 1 || !c_analyticBlurNinepatch) { 5514dca7a829635b552be369186ff508a94aba6a903reed if (!draw_rects_into_mask(smallR, count, &srcM)) { 5524dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 5534dca7a829635b552be369186ff508a94aba6a903reed } 5544dca7a829635b552be369186ff508a94aba6a903reed 5554dca7a829635b552be369186ff508a94aba6a903reed SkAutoMaskFreeImage amf(srcM.fImage); 5564dca7a829635b552be369186ff508a94aba6a903reed 5574dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 5584dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 5594dca7a829635b552be369186ff508a94aba6a903reed } 5604dca7a829635b552be369186ff508a94aba6a903reed } else { 5614dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, 5624dca7a829635b552be369186ff508a94aba6a903reed SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 5634dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 5644dca7a829635b552be369186ff508a94aba6a903reed } 5657c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 566b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed cache = add_cached_rects(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallR, count); 567d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 568dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fMask.fBounds.offsetTo(0, 0); 569dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fOuterRect = dstM.fBounds; 570dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fCenter = center; 57196fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == patch->fCache); 572b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed patch->fCache = cache; // transfer ownership to patch 573d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return kTrue_FilterReturn; 574d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com} 575d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 57630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comvoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 57730711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com SkRect* dst) const { 5787ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar pad = 3.0f * fSigma; 57917ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com 58017ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com dst->set(src.fLeft - pad, src.fTop - pad, 58117ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com src.fRight + pad, src.fBottom + pad); 5829efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com} 5839efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com 5849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { 5859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar sigma = buffer.readScalar(); 5869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const unsigned style = buffer.readUInt(); 5879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const unsigned flags = buffer.readUInt(); 5889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (style <= kLastEnum_SkBlurStyle) { 5899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkBlurMaskFilter::Create((SkBlurStyle)style, sigma, flags); 5909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 59196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 5929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5948b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { 59511e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com buffer.writeScalar(fSigma); 5969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.writeUInt(fBlurStyle); 597c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com buffer.writeUInt(fBlurFlags); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 600491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 6012b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 602cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgclass GrGLRectBlurEffect; 603cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 604b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrRectBlurEffect : public GrFragmentProcessor { 605cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgpublic: 60630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips ~GrRectBlurEffect() override { } 607cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 60836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "RectBlur"; } 609cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 61030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static GrFragmentProcessor* Create(GrTextureProvider *textureProvider, 61130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips const SkRect& rect, float sigma) { 6124a24cd8ff41a8b3d292d60e4351a631240a7ed75humper int doubleProfileSize = SkScalarCeilToInt(12*sigma); 6134a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 6144a24cd8ff41a8b3d292d60e4351a631240a7ed75humper if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) { 6154a24cd8ff41a8b3d292d60e4351a631240a7ed75humper // if the blur sigma is too large so the gaussian overlaps the whole 6164a24cd8ff41a8b3d292d60e4351a631240a7ed75humper // rect in either direction, fall back to CPU path for now. 61796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 618cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 6194a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 62030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkAutoTUnref<GrTexture> blurProfile(CreateBlurProfileTexture(textureProvider, sigma)); 62130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (!blurProfile) { 62296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 6234a24cd8ff41a8b3d292d60e4351a631240a7ed75humper } 624a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // in OpenGL ES, mediump floats have a minimum range of 2^14. If we have coordinates bigger 625a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // than that, the shader math will end up with infinities and result in the blur effect not 626a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // working correctly. To avoid this, we switch into highp when the coordinates are too big. 627a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // As 2^14 is the minimum range but the actual range can be bigger, we might end up 628a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // switching to highp sooner than strictly necessary, but most devices that have a bigger 629a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // range for mediump also have mediump being exactly the same as highp (e.g. all non-OpenGL 630a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas // ES devices), and thus incur no additional penalty for the switch. 631a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas static const SkScalar kMAX_BLUR_COORD = SkIntToScalar(16000); 632a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas GrSLPrecision precision; 633a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas if (SkScalarAbs(rect.top()) > kMAX_BLUR_COORD || 634a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas SkScalarAbs(rect.left()) > kMAX_BLUR_COORD || 635a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas SkScalarAbs(rect.bottom()) > kMAX_BLUR_COORD || 636a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas SkScalarAbs(rect.right()) > kMAX_BLUR_COORD || 637a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas SkScalarAbs(rect.width()) > kMAX_BLUR_COORD || 638a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas SkScalarAbs(rect.height()) > kMAX_BLUR_COORD) { 639a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas precision = kHigh_GrSLPrecision; 640a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas } 641a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas else { 642a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas precision = kDefault_GrSLPrecision; 643a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas } 644a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas return new GrRectBlurEffect(rect, sigma, blurProfile, precision); 645cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 6464c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 6474a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const SkRect& getRect() const { return fRect; } 648cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org float getSigma() const { return fSigma; } 649bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips GrSLPrecision precision() const { return fPrecision; } 650cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 651cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgprivate: 652a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile, 653a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas GrSLPrecision fPrecision); 654b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 65557d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 6564b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 65757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 6584b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 65936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor&) const override; 6604c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 66136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 6621a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 66330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static GrTexture* CreateBlurProfileTexture(GrTextureProvider*, float sigma); 6644c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 6654a24cd8ff41a8b3d292d60e4351a631240a7ed75humper SkRect fRect; 6664a24cd8ff41a8b3d292d60e4351a631240a7ed75humper float fSigma; 6674a24cd8ff41a8b3d292d60e4351a631240a7ed75humper GrTextureAccess fBlurProfileAccess; 668a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas GrSLPrecision fPrecision; 669cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 670b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 671cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 672b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 673cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}; 674cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 67564c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLRectBlurEffect : public GrGLSLFragmentProcessor { 676cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgpublic: 67730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips void emitCode(EmitArgs&) override; 678cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 679bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b); 680a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas 681b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 682018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 683cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 684cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgprivate: 685018fb62d12d1febf121fe265da5b6117b86a6541egdaniel typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 686cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 6874a24cd8ff41a8b3d292d60e4351a631240a7ed75humper UniformHandle fProxyRectUniform; 6884a24cd8ff41a8b3d292d60e4351a631240a7ed75humper UniformHandle fProfileSizeUniform; 689cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 69064c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 691cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}; 692cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 6938528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdaltonvoid OutputRectBlurProfileLookup(GrGLSLFPFragmentBuilder* fragBuilder, 6947dc4bd06fca73a97dcf3ad4a7425597160f1edfcegdaniel const GrGLSLTextureSampler& sampler, 6954a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *output, 6964a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *profileSize, const char *loc, 6974a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *blurred_width, 6984a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *sharp_width) { 6994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float %s;", output); 7004ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("{"); 7014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;", 7024a24cd8ff41a8b3d292d60e4351a631240a7ed75humper loc, blurred_width, sharp_width, profileSize); 7034ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = ", output); 7044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(sampler, "vec2(coord,0.5)"); 7054ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(".a;"); 7064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("}"); 7074a24cd8ff41a8b3d292d60e4351a631240a7ed75humper} 7084a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 709a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas 710bf536af15f4c176d3bef65b77b7592718bfd9068robertphillipsvoid GrGLRectBlurEffect::GenKey(const GrProcessor& proc, const GrGLSLCaps&, 711bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips GrProcessorKeyBuilder* b) { 712bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); 713bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips 714bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips b->add32(rbe.precision()); 715a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas} 716a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas 717a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas 7187c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLRectBlurEffect::emitCode(EmitArgs& args) { 719bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips const GrRectBlurEffect& rbe = args.fFp.cast<GrRectBlurEffect>(); 720bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips 7217ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 7224c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7234a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *rectName; 7244a24cd8ff41a8b3d292d60e4351a631240a7ed75humper const char *profileSizeName; 7254a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 726bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips const char* precisionString = GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, rbe.precision()); 7275e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 7287ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, 729bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips rbe.precision(), 7307ea439b2203855db97330b25945b87dd4b170b8begdaniel "proxyRect", 7317ea439b2203855db97330b25945b87dd4b170b8begdaniel &rectName); 7325e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 7337ea439b2203855db97330b25945b87dd4b170b8begdaniel kFloat_GrSLType, 7347ea439b2203855db97330b25945b87dd4b170b8begdaniel kDefault_GrSLPrecision, 7357ea439b2203855db97330b25945b87dd4b170b8begdaniel "profileSize", 7367ea439b2203855db97330b25945b87dd4b170b8begdaniel &profileSizeName); 7374a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 7388528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 7394ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char *fragmentPos = fragBuilder->fragmentPosition(); 7404c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7417c157a988845fb00f9024d6db6dda142c3458033wangyix if (args.fInputColor) { 7424ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor); 743cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } else { 7444ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec4 src=vec4(1);"); 745cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 7464c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7474ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s vec2 translatedPos = %s.xy - %s.xy;", precisionString, fragmentPos, 7484ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel rectName); 7494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString, rectName, rectName); 7504ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString, rectName, rectName); 7514c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7524ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s vec2 smallDims = vec2(width - %s, height - %s);", precisionString, 7534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel profileSizeName, profileSizeName); 7544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s float center = 2.0 * floor(%s/2.0 + .25) - 1.0;", precisionString, 7554ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel profileSizeName); 7564ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s vec2 wh = smallDims - vec2(center,center);", precisionString); 7574a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 7584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel OutputRectBlurProfileLookup(fragBuilder, args.fSamplers[0], "horiz_lookup", profileSizeName, 7597c157a988845fb00f9024d6db6dda142c3458033wangyix "translatedPos.x", "width", "wh.x"); 7604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel OutputRectBlurProfileLookup(fragBuilder, args.fSamplers[0], "vert_lookup", profileSizeName, 7617c157a988845fb00f9024d6db6dda142c3458033wangyix "translatedPos.y", "height", "wh.y"); 7624a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 7634ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float final = horiz_lookup * vert_lookup;"); 7644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = src * final;", args.fOutputColor); 765cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 766cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 767018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLRectBlurEffect::onSetData(const GrGLSLProgramDataManager& pdman, 76830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips const GrProcessor& proc) { 769b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); 7704a24cd8ff41a8b3d292d60e4351a631240a7ed75humper SkRect rect = rbe.getRect(); 7714a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 7727510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); 7737510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma())); 774cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 775cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 77630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillipsGrTexture* GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvider, 77730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips float sigma) { 778f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrSurfaceDesc texDesc; 7794c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 78024db3b1c35fb935660229da164fc5ad31977387fbsalomon unsigned int profileSize = SkScalarCeilToInt(6*sigma); 7814c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 78224db3b1c35fb935660229da164fc5ad31977387fbsalomon texDesc.fWidth = profileSize; 783cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org texDesc.fHeight = 1; 784cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org texDesc.fConfig = kAlpha_8_GrPixelConfig; 7854c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7868718aafec239c93485e45bbe8fed19d9a8def079bsalomon static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 7878718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrUniqueKey key; 7888718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrUniqueKey::Builder builder(&key, kDomain, 1); 78924db3b1c35fb935660229da164fc5ad31977387fbsalomon builder[0] = profileSize; 79024db3b1c35fb935660229da164fc5ad31977387fbsalomon builder.finish(); 7914c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 79230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips GrTexture *blurProfile = textureProvider->findAndRefTextureByUniqueKey(key); 7934c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 79430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (!blurProfile) { 79530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkAutoTDeleteArray<uint8_t> profile(SkBlurMask::ComputeBlurProfile(sigma)); 7964c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 7975ec26ae9bfca635ccc98283aad5deda11519d826bsalomon blurProfile = textureProvider->createTexture(texDesc, SkBudgeted::kYes, profile.get(), 0); 79830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (blurProfile) { 79930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips textureProvider->assignUniqueKeyToTexture(key, blurProfile); 800cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 801cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 8024c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 80330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return blurProfile; 804cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 805cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 806a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholasGrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile, 807a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas GrSLPrecision precision) 80830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips : fRect(rect) 80930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips , fSigma(sigma) 810a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas , fBlurProfileAccess(blurProfile) 811a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas , fPrecision(precision) { 812eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<GrRectBlurEffect>(); 8134a24cd8ff41a8b3d292d60e4351a631240a7ed75humper this->addTextureAccess(&fBlurProfileAccess); 8144a24cd8ff41a8b3d292d60e4351a631240a7ed75humper this->setWillReadFragmentPosition(); 815cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 816cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 81757d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrRectBlurEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 81857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 819bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips GrGLRectBlurEffect::GenKey(*this, caps, b); 820eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 821eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 82257d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const { 823bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips return new GrGLRectBlurEffect; 824cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 825cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 8260e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 82749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrRectBlurEffect& s = sBase.cast<GrRectBlurEffect>(); 8284a24cd8ff41a8b3d292d60e4351a631240a7ed75humper return this->getSigma() == s.getSigma() && this->getRect() == s.getRect(); 829cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 830cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 831605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrRectBlurEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 83256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt inout->mulByUnknownSingleComponent(); 833cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 834cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 835b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect); 836cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 837c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* GrRectBlurEffect::TestCreate(GrProcessorTestData* d) { 8380067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt float sigma = d->fRandom->nextRangeF(3,8); 8390067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt float width = d->fRandom->nextRangeF(200,300); 8400067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt float height = d->fRandom->nextRangeF(200,300); 8410067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrRectBlurEffect::Create(d->fContext->textureProvider(), SkRect::MakeWH(width, height), 842d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon sigma); 843cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 844cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 845cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 846ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillipsbool SkBlurMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider, 847ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrDrawContext* drawContext, 848cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org GrPaint* grp, 849570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const GrClip& clip, 8505531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix& viewMatrix, 851cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org const SkStrokeRec& strokeRec, 852cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org const SkPath& path) const { 853ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkASSERT(drawContext); 854ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 855e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (fBlurStyle != kNormal_SkBlurStyle) { 856cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 857cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 8584c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 85930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // TODO: we could handle blurred stroked circles 860cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org if (!strokeRec.isFillStyle()) { 861cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 862cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 8634c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 864ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); 8654a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 86630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkAutoTUnref<const GrFragmentProcessor> fp; 86730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 86830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkRect rect; 86930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (path.isRect(&rect)) { 87030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips int pad = SkScalarCeilToInt(6*xformedSigma)/2; 87130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); 87230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 87330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips fp.reset(GrRectBlurEffect::Create(texProvider, rect, xformedSigma)); 87430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height())) { 87530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips fp.reset(GrCircleBlurFragmentProcessor::Create(texProvider, rect, xformedSigma)); 87630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 87730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // expand the rect for the coverage geometry 87830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips int pad = SkScalarCeilToInt(6*xformedSigma)/2; 87930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); 88030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } else { 88130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return false; 88230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 8834c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 884b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (!fp) { 885cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 886cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 887cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 888ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon grp->addCoverageFragmentProcessor(fp); 8894c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 890c2625821b34d89e8df2ba89cc84db6957189f250joshualitt SkMatrix inverse; 891c2625821b34d89e8df2ba89cc84db6957189f250joshualitt if (!viewMatrix.invert(&inverse)) { 892c2625821b34d89e8df2ba89cc84db6957189f250joshualitt return false; 893c2625821b34d89e8df2ba89cc84db6957189f250joshualitt } 894ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 895a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), rect, inverse); 896ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips return true; 897cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 898cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 89930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips////////////////////////////////////////////////////////////////////////////// 90030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 901b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrRRectBlurEffect : public GrFragmentProcessor { 9023d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgpublic: 9033d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 90430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static const GrFragmentProcessor* Create(GrTextureProvider*, float sigma, const SkRRect&); 9053d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9063d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org virtual ~GrRRectBlurEffect() {}; 90736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "GrRRectBlur"; } 9083d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9093d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org const SkRRect& getRRect() const { return fRRect; } 9103d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org float getSigma() const { return fSigma; } 9113d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9123d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgprivate: 91357d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 914b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 9153d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture); 9163d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 91757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, 91857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const override; 9194b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 92036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor& other) const override; 9213d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 92236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 9231a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 9243d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRRect fRRect; 9253d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org float fSigma; 9263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org GrTextureAccess fNinePatchAccess; 9273d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 928b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 9293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 930b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 9313d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}; 9323d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9333d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 93430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillipsconst GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvider, float sigma, 93530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips const SkRRect& rrect) { 93630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (rrect.isCircle()) { 93730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return GrCircleBlurFragmentProcessor::Create(texProvider, rrect.rect(), sigma); 93830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 93930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 9403d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (!rrect.isSimpleCircular()) { 94196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 9423d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 9433d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9443d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // Make sure we can successfully ninepatch this rrect -- the blur sigma has to be 9453d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // sufficiently small relative to both the size of the corner radius and the 9463d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // width (and height) of the rrect. 9473d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9483d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f); 9493d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x()); 9503d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (cornerRadius + blurRadius > rrect.width()/2 || 9513d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org cornerRadius + blurRadius > rrect.height()/2) { 95296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 9533d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 9543d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9558718aafec239c93485e45bbe8fed19d9a8def079bsalomon static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 9568718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrUniqueKey key; 9578718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrUniqueKey::Builder builder(&key, kDomain, 2); 95824db3b1c35fb935660229da164fc5ad31977387fbsalomon builder[0] = blurRadius; 95924db3b1c35fb935660229da164fc5ad31977387fbsalomon builder[1] = cornerRadius; 96024db3b1c35fb935660229da164fc5ad31977387fbsalomon builder.finish(); 9613d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 962ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkAutoTUnref<GrTexture> blurNinePatchTexture(texProvider->findAndRefTextureByUniqueKey(key)); 9633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 964d5b98404ece3b1d29bc47f75dec58430d16e39e5joshualitt if (!blurNinePatchTexture) { 9653d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkMask mask; 9663d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 96737f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1; 96837f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon 9693d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org mask.fBounds = SkIRect::MakeWH(smallRectSide, smallRectSide); 9703d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org mask.fFormat = SkMask::kA8_Format; 9713d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org mask.fRowBytes = mask.fBounds.width(); 9723d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org mask.fImage = SkMask::AllocImage(mask.computeTotalImageSize()); 9733d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkAutoMaskFreeImage amfi(mask.fImage); 9743d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9753d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org memset(mask.fImage, 0, mask.computeTotalImageSize()); 9763d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9773d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRect smallRect; 9783d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org smallRect.setWH(SkIntToScalar(smallRectSide), SkIntToScalar(smallRectSide)); 9793d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9803d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRRect smallRRect; 9813d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius)); 9823d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 9833d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkPath path; 984a8e5fbdf30fb1a09c781c4aab91ec70839590626ethannicholas path.addRRect(smallRRect); 9853d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 98696fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkDraw::DrawToMask(path, &mask.fBounds, nullptr, nullptr, &mask, 98737f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style); 9883d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 989d5b98404ece3b1d29bc47f75dec58430d16e39e5joshualitt SkMask blurredMask; 990e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips if (!SkBlurMask::BoxBlur(&blurredMask, mask, sigma, kNormal_SkBlurStyle, 991e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips kHigh_SkBlurQuality, nullptr, true)) { 992e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips return nullptr; 993e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips } 99437f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon 99537f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon unsigned int texSide = smallRectSide + 2*blurRadius; 99637f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon GrSurfaceDesc texDesc; 99737f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon texDesc.fWidth = texSide; 99837f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon texDesc.fHeight = texSide; 99937f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon texDesc.fConfig = kAlpha_8_GrPixelConfig; 100037f9a2694c15f08e361ebda74fe9f0fffbf452aabsalomon 1001d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon blurNinePatchTexture.reset( 10025ec26ae9bfca635ccc98283aad5deda11519d826bsalomon texProvider->createTexture(texDesc, SkBudgeted::kYes , blurredMask.fImage, 0)); 1003d5b98404ece3b1d29bc47f75dec58430d16e39e5joshualitt SkMask::FreeImage(blurredMask.fImage); 10045f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt if (!blurNinePatchTexture) { 100596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 10065f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt } 1007ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips texProvider->assignUniqueKeyToTexture(key, blurNinePatchTexture); 10083d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 1009385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GrRRectBlurEffect(sigma, rrect, blurNinePatchTexture); 10103d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 10113d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1012605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrRRectBlurEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 101356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt inout->mulByUnknownSingleComponent(); 10143d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 10153d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10163d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgGrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture) 10173d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org : fRRect(rrect), 10183d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org fSigma(sigma), 10193d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org fNinePatchAccess(ninePatchTexture) { 1020eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<GrRRectBlurEffect>(); 10213d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org this->addTextureAccess(&fNinePatchAccess); 10223d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org this->setWillReadFragmentPosition(); 10233d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 10243d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10250e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrRRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const { 102649586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrRRectBlurEffect& rrbe = other.cast<GrRRectBlurEffect>(); 10273d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return fRRect.getSimpleRadii().fX == rrbe.fRRect.getSimpleRadii().fX && fSigma == rrbe.fSigma; 10283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 10293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10303d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 10313d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1032b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRRectBlurEffect); 10333d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1034c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* GrRRectBlurEffect::TestCreate(GrProcessorTestData* d) { 10350067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar w = d->fRandom->nextRangeScalar(100.f, 1000.f); 10360067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar h = d->fRandom->nextRangeScalar(100.f, 1000.f); 10370067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar r = d->fRandom->nextRangeF(1.f, 9.f); 10380067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt SkScalar sigma = d->fRandom->nextRangeF(1.f,10.f); 10393d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRRect rrect; 10403d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org rrect.setRectXY(SkRect::MakeWH(w, h), r, r); 1041ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips return GrRRectBlurEffect::Create(d->fContext->textureProvider(), sigma, rrect); 10423d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 10433d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10443d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////// 10453d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 104664c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLRRectBlurEffect : public GrGLSLFragmentProcessor { 10473d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgpublic: 10489cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips void emitCode(EmitArgs&) override; 10493d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1050b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 1051018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 10523d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10533d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgprivate: 1054018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fProxyRectUniform; 1055018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fCornerRadiusUniform; 1056018fb62d12d1febf121fe265da5b6117b86a6541egdaniel GrGLSLProgramDataManager::UniformHandle fBlurRadiusUniform; 105764c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 10583d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}; 10593d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10607c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLRRectBlurEffect::emitCode(EmitArgs& args) { 10613d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org const char *rectName; 10623d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org const char *cornerRadiusName; 10633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org const char *blurRadiusName; 10643d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10657ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 10663d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // The proxy rect has left, top, right, and bottom edges correspond to 10673d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // components x, y, z, and w, respectively. 10683d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10695e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 10707ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, 10712d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel kDefault_GrSLPrecision, 10727ea439b2203855db97330b25945b87dd4b170b8begdaniel "proxyRect", 10737ea439b2203855db97330b25945b87dd4b170b8begdaniel &rectName); 10745e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fCornerRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 10757ea439b2203855db97330b25945b87dd4b170b8begdaniel kFloat_GrSLType, 10767ea439b2203855db97330b25945b87dd4b170b8begdaniel kDefault_GrSLPrecision, 10777ea439b2203855db97330b25945b87dd4b170b8begdaniel "cornerRadius", 10787ea439b2203855db97330b25945b87dd4b170b8begdaniel &cornerRadiusName); 10795e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fBlurRadiusUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 10807ea439b2203855db97330b25945b87dd4b170b8begdaniel kFloat_GrSLType, 10817ea439b2203855db97330b25945b87dd4b170b8begdaniel kDefault_GrSLPrecision, 10827ea439b2203855db97330b25945b87dd4b170b8begdaniel "blurRadius", 10837ea439b2203855db97330b25945b87dd4b170b8begdaniel &blurRadiusName); 10842d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel 10858528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 10864ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* fragmentPos = fragBuilder->fragmentPosition(); 10873d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10883d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org // warp the fragment position to the appropriate part of the 9patch blur texture 10893d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 10904ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName); 10914ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 translatedFragPos = %s.xy - %s.xy;", fragmentPos, rectName); 10924ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName); 10934ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName); 10944ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 10954ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf( 10964ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel "if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {"); 10974ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("translatedFragPos.x = threshold;\n"); 10984ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("} else if (translatedFragPos.x >= (middle.x + threshold)) {"); 10994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("translatedFragPos.x -= middle.x - 1.0;"); 11004ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("}"); 11014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 11024ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf( 11034ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel "if (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {"); 11044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("translatedFragPos.y = threshold;"); 11054ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("} else if (translatedFragPos.y >= (middle.y + threshold)) {"); 11064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("translatedFragPos.y -= middle.y - 1.0;"); 11074ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("}"); 11084ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 11094ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 proxyDims = vec2(2.0*threshold+1.0);"); 11104ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 texCoord = translatedFragPos / proxyDims;"); 11114ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 11124ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = ", args.fOutputColor); 11134ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers[0], "texCoord"); 11144ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";"); 11153d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 11163d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1117018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLRRectBlurEffect::onSetData(const GrGLSLProgramDataManager& pdman, 1118018fb62d12d1febf121fe265da5b6117b86a6541egdaniel const GrProcessor& proc) { 1119b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrRRectBlurEffect& brre = proc.cast<GrRRectBlurEffect>(); 11203d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRRect rrect = brre.getRRect(); 11213d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 11223d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org float blurRadius = 3.f*SkScalarCeilToScalar(brre.getSigma()-1/6.0f); 11237510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fBlurRadiusUniform, blurRadius); 11243d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 11253d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkRect rect = rrect.getBounds(); 11263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org rect.outset(blurRadius, blurRadius); 11277510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); 11283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 11293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkScalar radius = 0; 11303d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org SkASSERT(rrect.isSimpleCircular() || rrect.isRect()); 11313d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org radius = rrect.getSimpleRadii().fX; 11327510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fCornerRadiusUniform, radius); 11333d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org} 11343d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 113557d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrRRectBlurEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 113657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 1137eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrGLRRectBlurEffect::GenKey(*this, caps, b); 1138eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 1139eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 114057d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrRRectBlurEffect::onCreateGLSLInstance() const { 11419cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips return new GrGLRRectBlurEffect; 1142eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 11433d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1144ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillipsbool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvider, 1145ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips GrDrawContext* drawContext, 1146821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org GrPaint* grp, 1147570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const GrClip& clip, 11485531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix& viewMatrix, 1149821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org const SkStrokeRec& strokeRec, 1150821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org const SkRRect& rrect) const { 1151ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkASSERT(drawContext); 1152ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 11533d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (fBlurStyle != kNormal_SkBlurStyle) { 11543d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 11553d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 11563d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 11573d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (!strokeRec.isFillStyle()) { 11583d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 11593d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 11603d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1161ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); 11623d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); 11633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1164ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkRect proxyRect = rrect.rect(); 1165ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips proxyRect.outset(extra, extra); 1166ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 116730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkAutoTUnref<const GrFragmentProcessor> fp(GrRRectBlurEffect::Create(texProvider, 116830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips xformedSigma, rrect)); 1169b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (!fp) { 11703d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 11713d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 11723d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1173ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon grp->addCoverageFragmentProcessor(fp); 11743d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 1175c2625821b34d89e8df2ba89cc84db6957189f250joshualitt SkMatrix inverse; 1176c2625821b34d89e8df2ba89cc84db6957189f250joshualitt if (!viewMatrix.invert(&inverse)) { 1177c2625821b34d89e8df2ba89cc84db6957189f250joshualitt return false; 1178c2625821b34d89e8df2ba89cc84db6957189f250joshualitt } 1179ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 1180a2e69fcdedbd9a7762620e0e9dcdd86596369cffbsalomon drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), proxyRect, inverse); 1181ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips return true; 1182821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org} 1183821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org 118430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillipsbool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, 1185491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com const SkIRect& clipBounds, 1186491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com const SkMatrix& ctm, 1187491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com SkRect* maskRect) const { 11887ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar xformedSigma = this->computeXformedSigma(ctm); 11897ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com if (xformedSigma <= 0) { 1190491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return false; 11912b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com } 1192491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 119330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // We always do circles on the GPU 119430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (!devRRect.isCircle()) { 119530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); 119630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); 1197491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 119830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (devRRect.width() <= kMIN_GPU_BLUR_SIZE && 119930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips devRRect.height() <= kMIN_GPU_BLUR_SIZE && 120030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips xformedSigma <= kMIN_GPU_BLUR_SIGMA) { 120130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // We prefer to blur small rects with small radii on the CPU. 120230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return false; 120330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 1204491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1205491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 120696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == maskRect) { 1207491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // don't need to compute maskRect 1208491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return true; 1209491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1210491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 12117ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float sigma3 = 3 * SkScalarToFloat(xformedSigma); 1212491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 12134469938e92d779dff05e745559e67907bbf21e78reed@google.com SkRect clipRect = SkRect::Make(clipBounds); 121430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkRect srcRect(devRRect.rect()); 1215491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1216491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. 12174b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org srcRect.outset(sigma3, sigma3); 12184b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org clipRect.outset(sigma3, sigma3); 1219f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips if (!srcRect.intersect(clipRect)) { 1220f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips srcRect.setEmpty(); 1221f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips } 1222491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com *maskRect = srcRect; 12231842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com return true; 1224491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com} 1225491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 12261842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, 1227439ff1b9ca2b74a9dc3b04346aa1032c11b142e9commit-bot@chromium.org const SkMatrix& ctm, 12281842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com const SkRect& maskRect, 1229491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com GrTexture** result, 1230491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com bool canOverwriteSrc) const { 1231491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); 1232491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1233491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com GrContext* context = src->getContext(); 1234491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1235439ff1b9ca2b74a9dc3b04346aa1032c11b142e9commit-bot@chromium.org SkScalar xformedSigma = this->computeXformedSigma(ctm); 12367ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkASSERT(xformedSigma > 0); 1237491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1238491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // If we're doing a normal blur, we can clobber the pathTexture in the 1239491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // gaussianBlur. Otherwise, we need to save it for later compositing. 1240e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle); 1241736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc, 12424e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed clipRect, nullptr, xformedSigma, xformedSigma); 124396fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == *result) { 1244491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return false; 1245491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1246491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1247491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com if (!isNormalBlur) { 1248491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com GrPaint paint; 1249491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com SkMatrix matrix; 1250491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com matrix.setIDiv(src->width(), src->height()); 1251491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // Blend pathTexture over blurTexture. 12524a339529612a43871d021877e58698e067d6c4cdbsalomon paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(src, matrix))->unref(); 1253e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle) { 1254491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // inner: dst = dst * src 1255b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kIntersect_Op); 1256e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } else if (kSolid_SkBlurStyle == fBlurStyle) { 1257491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // solid: dst = src + dst - src * dst 1258b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel // = src + (1 - src) * dst 1259b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kUnion_Op); 1260e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } else if (kOuter_SkBlurStyle == fBlurStyle) { 1261491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // outer: dst = dst * (1 - src) 1262491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // = 0 * src + (1 - src) * dst 1263b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kDifference_Op); 1264c4b72720e75313079212e69e46a5ef7c474b2305egdaniel } else { 1265c4b72720e75313079212e69e46a5ef7c474b2305egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); 1266491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1267ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 12682e1e51f04985f7c258b96f0decc190456f5dd74drobertphillips SkAutoTUnref<GrDrawContext> drawContext(context->drawContext((*result)->asRenderTarget())); 1269ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips if (!drawContext) { 1270ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips return false; 1271ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips } 1272ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 12732e1e51f04985f7c258b96f0decc190456f5dd74drobertphillips drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), clipRect); 1274491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1275491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1276491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return true; 12772b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com} 12782b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1279491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif // SK_SUPPORT_GPU 1280491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1281491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 12820f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 12830bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.comvoid SkBlurMaskFilterImpl::toString(SkString* str) const { 12840bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("SkBlurMaskFilterImpl: ("); 12850bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 12867ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com str->append("sigma: "); 12877ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com str->appendScalar(fSigma); 12880bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append(" "); 12890bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 1290e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = { 12910bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com "normal", "solid", "outer", "inner" 12920bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com }; 12930bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 12940bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->appendf("style: %s ", gStyleName[fBlurStyle]); 12950bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("flags: ("); 12960bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com if (fBlurFlags) { 12970bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com bool needSeparator = false; 12988eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkAddFlagToString(str, 12998eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag), 13000bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com "IgnoreXform", &needSeparator); 13018eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkAddFlagToString(str, 13028eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag), 13030bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com "HighQuality", &needSeparator); 13040bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com } else { 13050bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("None"); 13060bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com } 13070bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("))"); 13080bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com} 13090bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#endif 13100bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 1311d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1312d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1313d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1314