Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/effects/SkBlurMaskFilter.cpp

Issue 471473002: Optimize CSS box-shadow performance (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add SkMaskCache Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/core/SkScaledImageCache.cpp ('K') | « src/effects/SkBlurMask.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkBlurMaskFilter.h" 9 #include "SkBlurMaskFilter.h"
10 #include "SkBlurMask.h" 10 #include "SkBlurMask.h"
11 #include "SkGpuBlurUtils.h" 11 #include "SkGpuBlurUtils.h"
12 #include "SkReadBuffer.h" 12 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
14 #include "SkMaskCache.h"
14 #include "SkMaskFilter.h" 15 #include "SkMaskFilter.h"
15 #include "SkRRect.h" 16 #include "SkRRect.h"
16 #include "SkRTConf.h" 17 #include "SkRTConf.h"
17 #include "SkStringUtils.h" 18 #include "SkStringUtils.h"
18 #include "SkStrokeRec.h" 19 #include "SkStrokeRec.h"
19 20
20 #if SK_SUPPORT_GPU 21 #if SK_SUPPORT_GPU
21 #include "GrContext.h" 22 #include "GrContext.h"
22 #include "GrTexture.h" 23 #include "GrTexture.h"
23 #include "GrEffect.h" 24 #include "GrEffect.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 virtual bool filterMaskGPU(GrTexture* src, 60 virtual bool filterMaskGPU(GrTexture* src,
60 const SkMatrix& ctm, 61 const SkMatrix& ctm,
61 const SkRect& maskRect, 62 const SkRect& maskRect,
62 GrTexture** result, 63 GrTexture** result,
63 bool canOverwriteSrc) const SK_OVERRIDE; 64 bool canOverwriteSrc) const SK_OVERRIDE;
64 #endif 65 #endif
65 66
66 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; 67 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
67 virtual bool asABlur(BlurRec*) const SK_OVERRIDE; 68 virtual bool asABlur(BlurRec*) const SK_OVERRIDE;
68 69
70 static bool getCachedBlurMask(SkScalar sigma,
71 unsigned rectCount,
72 const SkRect rects[],
73 SkCachedMask &mask);
74 static bool getCachedBlurMask(SkScalar sigma,
75 const SkRRect rrect,
76 SkCachedMask &mask);
77
69 SK_TO_STRING_OVERRIDE() 78 SK_TO_STRING_OVERRIDE()
70 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) 79 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
71 80
72 protected: 81 protected:
73 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa trix&, 82 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa trix&,
74 const SkIRect& clipBounds, 83 const SkIRect& clipBounds,
75 NinePatch*) const SK_OVERRIDE; 84 NinePatch*) const SK_OVERRIDE;
76 85
77 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, 86 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
78 const SkIRect& clipBounds, 87 const SkIRect& clipBounds,
(...skipping 29 matching lines...) Expand all
108 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); 117 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA);
109 } 118 }
110 119
111 friend class SkBlurMaskFilter; 120 friend class SkBlurMaskFilter;
112 121
113 typedef SkMaskFilter INHERITED; 122 typedef SkMaskFilter INHERITED;
114 }; 123 };
115 124
116 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); 125 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
117 126
127 bool SkBlurMaskFilterImpl::getCachedBlurMask(SkScalar sigma,
reed1 2014/08/25 11:58:42 Do we really need these helper methods? The caller
qiankun 2014/08/26 08:36:33 Done.
128 const SkRRect rrect,
129 SkCachedMask &mask) {
reed1 2014/08/25 11:58:42 skia's convention is to only use reference-paramet
qiankun 2014/08/26 08:36:33 Done.
130 SkMaskCache::ID* cacheId = SkMaskCache::FindAndLock(sigma, rrect, &mask.fMas k);
131 mask.fCacheId = cacheId;
reed1 2014/08/25 11:58:42 Skia's convention is to not set the result fields
qiankun 2014/08/26 08:36:33 Done.
132 return cacheId ? true : false;
133 }
134
135 bool SkBlurMaskFilterImpl::getCachedBlurMask(SkScalar sigma,
136 unsigned rectCount,
137 const SkRect rects[],
138 SkCachedMask &mask) {
139 SkMaskCache::ID* cacheId = SkMaskCache::FindAndLock(sigma, rectCount, rects, &mask.fMask);
140 mask.fCacheId = cacheId;
141 return cacheId ? true : false;
142 }
143
118 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32 _t flags) { 144 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32 _t flags) {
119 if (!SkScalarIsFinite(sigma) || sigma <= 0) { 145 if (!SkScalarIsFinite(sigma) || sigma <= 0) {
120 return NULL; 146 return NULL;
121 } 147 }
122 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { 148 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) {
123 return NULL; 149 return NULL;
124 } 150 }
125 if (flags > SkBlurMaskFilter::kAll_BlurFlag) { 151 if (flags > SkBlurMaskFilter::kAll_BlurFlag) {
126 return NULL; 152 return NULL;
127 } 153 }
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); 387 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight);
362 388
363 SkRRect smallRR; 389 SkRRect smallRR;
364 SkVector radii[4]; 390 SkVector radii[4];
365 radii[SkRRect::kUpperLeft_Corner] = UL; 391 radii[SkRRect::kUpperLeft_Corner] = UL;
366 radii[SkRRect::kUpperRight_Corner] = UR; 392 radii[SkRRect::kUpperRight_Corner] = UR;
367 radii[SkRRect::kLowerRight_Corner] = LR; 393 radii[SkRRect::kLowerRight_Corner] = LR;
368 radii[SkRRect::kLowerLeft_Corner] = LL; 394 radii[SkRRect::kLowerLeft_Corner] = LL;
369 smallRR.setRectRadii(smallR, radii); 395 smallRR.setRectRadii(smallR, radii);
370 396
397 SkScalar sigma = this->computeXformedSigma(matrix);
398 SkCachedMask cachedBlurMask;
399 cachedBlurMask.fCacheId = NULL;
400 if (getCachedBlurMask(sigma, rrect, cachedBlurMask)) {
401 patch->fCachedMask = cachedBlurMask;
402 patch->fOuterRect = dstM.fBounds;
403 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1;
404 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1;
405 return kTrue_FilterReturn;
406 }
407
371 bool analyticBlurWorked = false; 408 bool analyticBlurWorked = false;
372 if (c_analyticBlurRRect) { 409 if (c_analyticBlurRRect) {
373 analyticBlurWorked = 410 analyticBlurWorked =
374 this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, 411 this->filterRRectMask(&(patch->fCachedMask.fMask), smallRR, matrix, &margin,
375 SkMask::kComputeBoundsAndRenderImage_CreateMod e); 412 SkMask::kComputeBoundsAndRenderImage_CreateMod e);
376 } 413 }
377 414
378 if (!analyticBlurWorked) { 415 if (!analyticBlurWorked) {
379 if (!draw_rrect_into_mask(smallRR, &srcM)) { 416 if (!draw_rrect_into_mask(smallRR, &srcM)) {
380 return kFalse_FilterReturn; 417 return kFalse_FilterReturn;
381 } 418 }
382 419
383 SkAutoMaskFreeImage amf(srcM.fImage); 420 SkAutoMaskFreeImage amf(srcM.fImage);
384 421
385 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 422 if (!this->filterMask(&(patch->fCachedMask.fMask), srcM, matrix, &margin )) {
386 return kFalse_FilterReturn; 423 return kFalse_FilterReturn;
387 } 424 }
388 } 425 }
389 426
390 patch->fMask.fBounds.offsetTo(0, 0); 427 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0);
391 patch->fOuterRect = dstM.fBounds; 428 patch->fOuterRect = dstM.fBounds;
392 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; 429 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1;
393 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; 430 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1;
431 if (!cachedBlurMask.fCacheId) {
432 patch->fCachedMask.fCacheId = SkMaskCache::AddAndLock(sigma, rrect,
433 patch->fCachedMask .fMask);
434 }
435
394 return kTrue_FilterReturn; 436 return kTrue_FilterReturn;
395 } 437 }
396 438
397 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" ); 439 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
398 440
399 SkMaskFilter::FilterReturn 441 SkMaskFilter::FilterReturn
400 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, 442 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
401 const SkMatrix& matrix, 443 const SkMatrix& matrix,
402 const SkIRect& clipBounds, 444 const SkIRect& clipBounds,
403 NinePatch* patch) const { 445 NinePatch* patch) const {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 if (1 == count) { 505 if (1 == count) {
464 innerIR = srcM.fBounds; 506 innerIR = srcM.fBounds;
465 center.set(smallW, smallH); 507 center.set(smallW, smallH);
466 } else { 508 } else {
467 SkASSERT(2 == count); 509 SkASSERT(2 == count);
468 rects[1].roundIn(&innerIR); 510 rects[1].roundIn(&innerIR);
469 center.set(smallW + (innerIR.left() - srcM.fBounds.left()), 511 center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
470 smallH + (innerIR.top() - srcM.fBounds.top())); 512 smallH + (innerIR.top() - srcM.fBounds.top()));
471 } 513 }
472 514
515 SkScalar sigma = this->computeXformedSigma(matrix);
516 SkCachedMask cachedBlurMask;
517 cachedBlurMask.fCacheId = NULL;
518 if (getCachedBlurMask(sigma, count, rects, cachedBlurMask)) {
519 patch->fCachedMask = cachedBlurMask;
520 patch->fOuterRect = dstM.fBounds;
521 patch->fCenter = center;
522 return kTrue_FilterReturn;
523 }
524
473 // +1 so we get a clean, stretchable, center row/col 525 // +1 so we get a clean, stretchable, center row/col
474 smallW += 1; 526 smallW += 1;
475 smallH += 1; 527 smallH += 1;
476 528
477 // we want the inset amounts to be integral, so we don't change any 529 // we want the inset amounts to be integral, so we don't change any
478 // fractional phase on the fRight or fBottom of our smallR. 530 // fractional phase on the fRight or fBottom of our smallR.
479 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); 531 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
480 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); 532 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
481 if (dx < 0 || dy < 0) { 533 if (dx < 0 || dy < 0) {
482 // we're too small, relative to our blur, to break into nine-patch, 534 // we're too small, relative to our blur, to break into nine-patch,
483 // so we ask to have our normal filterMask() be called. 535 // so we ask to have our normal filterMask() be called.
484 return kUnimplemented_FilterReturn; 536 return kUnimplemented_FilterReturn;
485 } 537 }
486 538
487 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[ 0].bottom() - dy); 539 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[ 0].bottom() - dy);
488 if (smallR[0].width() < 2 || smallR[0].height() < 2) { 540 if (smallR[0].width() < 2 || smallR[0].height() < 2) {
489 return kUnimplemented_FilterReturn; 541 return kUnimplemented_FilterReturn;
490 } 542 }
491 if (2 == count) { 543 if (2 == count) {
492 smallR[1].set(rects[1].left(), rects[1].top(), 544 smallR[1].set(rects[1].left(), rects[1].top(),
493 rects[1].right() - dx, rects[1].bottom() - dy); 545 rects[1].right() - dx, rects[1].bottom() - dy);
494 SkASSERT(!smallR[1].isEmpty()); 546 SkASSERT(!smallR[1].isEmpty());
495 } 547 }
496 548
497 if (count > 1 || !c_analyticBlurNinepatch) { 549 if (count > 1 || !c_analyticBlurNinepatch) {
498 if (!draw_rects_into_mask(smallR, count, &srcM)) { 550 if (!draw_rects_into_mask(smallR, count, &srcM)) {
499 return kFalse_FilterReturn; 551 return kFalse_FilterReturn;
500 } 552 }
501
502 SkAutoMaskFreeImage amf(srcM.fImage); 553 SkAutoMaskFreeImage amf(srcM.fImage);
503 554
504 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 555 if (!this->filterMask(&patch->fCachedMask.fMask, srcM, matrix, &margin)) {
505 return kFalse_FilterReturn; 556 return kFalse_FilterReturn;
506 } 557 }
507 } else { 558 } else {
508 if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, 559 if (!this->filterRectMask(&patch->fCachedMask.fMask, smallR[0], matrix, &margin,
509 SkMask::kComputeBoundsAndRenderImage_CreateMod e)) { 560 SkMask::kComputeBoundsAndRenderImage_CreateMod e)) {
510 return kFalse_FilterReturn; 561 return kFalse_FilterReturn;
511 } 562 }
512 } 563 }
513 patch->fMask.fBounds.offsetTo(0, 0); 564 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0);
514 patch->fOuterRect = dstM.fBounds; 565 patch->fOuterRect = dstM.fBounds;
515 patch->fCenter = center; 566 patch->fCenter = center;
567 if (!cachedBlurMask.fCacheId) {
568 patch->fCachedMask.fCacheId = SkMaskCache::AddAndLock(sigma, count, rect s,
569 patch->fCachedMask .fMask);
570 }
571
516 return kTrue_FilterReturn; 572 return kTrue_FilterReturn;
517 } 573 }
518 574
519 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 575 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
520 SkRect* dst) const { 576 SkRect* dst) const {
521 SkScalar pad = 3.0f * fSigma; 577 SkScalar pad = 3.0f * fSigma;
522 578
523 dst->set(src.fLeft - pad, src.fTop - pad, 579 dst->set(src.fLeft - pad, src.fTop - pad,
524 src.fRight + pad, src.fBottom + pad); 580 src.fRight + pad, src.fBottom + pad);
525 } 581 }
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 } else { 1275 } else {
1220 str->append("None"); 1276 str->append("None");
1221 } 1277 }
1222 str->append("))"); 1278 str->append("))");
1223 } 1279 }
1224 #endif 1280 #endif
1225 1281
1226 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1282 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1227 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1283 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1228 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1284 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« src/core/SkScaledImageCache.cpp ('K') | « src/effects/SkBlurMask.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698