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

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: based on SkBitmapCache Created 6 years, 4 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.h ('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 "SkBitmapCache.h"
9 #include "SkBlurMaskFilter.h" 10 #include "SkBlurMaskFilter.h"
10 #include "SkBlurMask.h" 11 #include "SkBlurMask.h"
11 #include "SkGpuBlurUtils.h" 12 #include "SkGpuBlurUtils.h"
12 #include "SkReadBuffer.h" 13 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h" 14 #include "SkWriteBuffer.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"
(...skipping 40 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,
128 const SkRRect rrect,
129 SkCachedMask &mask) {
130 SkBitmap bitmap;
131 SkBitmapCache::ID* cacheId = SkBitmapCache::FindAndLock(sigma, rrect, &bitma p);
132 if (cacheId) {
133 SkAutoLockPixels autoLockPixels(bitmap);
134 if (bitmap.getPixels()) {
135 mask.fMask.fBounds.set(0, 0, bitmap.width(), bitmap.height());
136 mask.fMask.fRowBytes = mask.fMask.fBounds.width();
137 mask.fMask.fFormat = SkMask::kA8_Format;
138 mask.fMask.fImage = static_cast<uint8_t*>(bitmap.getPixels());
139 mask.fCacheId = cacheId;
140 return true;
141 }
142 }
143 return false;
144 }
145
146 bool SkBlurMaskFilterImpl::getCachedBlurMask(SkScalar sigma,
147 unsigned rectCount,
148 const SkRect rects[],
149 SkCachedMask &mask) {
150 SkBitmap bitmap;
151 SkBitmapCache::ID* cacheId = SkBitmapCache::FindAndLock(sigma, rectCount, re cts, &bitmap);
152 if (cacheId) {
153 SkAutoLockPixels autoLockPixels(bitmap);
154 if (bitmap.getPixels()) {
155 mask.fMask.fBounds.set(0, 0, bitmap.width(), bitmap.height());
156 mask.fMask.fRowBytes = mask.fMask.fBounds.width();
157 mask.fMask.fFormat = SkMask::kA8_Format;
158 mask.fMask.fImage = static_cast<uint8_t*>(bitmap.getPixels());
159 mask.fCacheId = cacheId;
160 return true;
161 }
162 }
163 return false;
164 }
165
118 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32 _t flags) { 166 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32 _t flags) {
119 if (!SkScalarIsFinite(sigma) || sigma <= 0) { 167 if (!SkScalarIsFinite(sigma) || sigma <= 0) {
120 return NULL; 168 return NULL;
121 } 169 }
122 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { 170 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) {
123 return NULL; 171 return NULL;
124 } 172 }
125 if (flags > SkBlurMaskFilter::kAll_BlurFlag) { 173 if (flags > SkBlurMaskFilter::kAll_BlurFlag) {
126 return NULL; 174 return NULL;
127 } 175 }
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); 409 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight);
362 410
363 SkRRect smallRR; 411 SkRRect smallRR;
364 SkVector radii[4]; 412 SkVector radii[4];
365 radii[SkRRect::kUpperLeft_Corner] = UL; 413 radii[SkRRect::kUpperLeft_Corner] = UL;
366 radii[SkRRect::kUpperRight_Corner] = UR; 414 radii[SkRRect::kUpperRight_Corner] = UR;
367 radii[SkRRect::kLowerRight_Corner] = LR; 415 radii[SkRRect::kLowerRight_Corner] = LR;
368 radii[SkRRect::kLowerLeft_Corner] = LL; 416 radii[SkRRect::kLowerLeft_Corner] = LL;
369 smallRR.setRectRadii(smallR, radii); 417 smallRR.setRectRadii(smallR, radii);
370 418
419 SkScalar sigma = this->computeXformedSigma(matrix);
420 SkCachedMask cachedBlurMask;
421 cachedBlurMask.fCacheId = NULL;
422 if (getCachedBlurMask(sigma, rrect, cachedBlurMask)) {
423 patch->fCachedMask = cachedBlurMask;
424 patch->fOuterRect = dstM.fBounds;
425 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1;
426 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1;
427 return kTrue_FilterReturn;
428 }
429
371 bool analyticBlurWorked = false; 430 bool analyticBlurWorked = false;
372 if (c_analyticBlurRRect) { 431 if (c_analyticBlurRRect) {
373 analyticBlurWorked = 432 analyticBlurWorked =
374 this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, 433 this->filterRRectMask(&(patch->fCachedMask.fMask), smallRR, matrix, &margin,
375 SkMask::kComputeBoundsAndRenderImage_CreateMod e); 434 SkMask::kComputeBoundsAndRenderImage_CreateMod e);
376 } 435 }
377 436
378 if (!analyticBlurWorked) { 437 if (!analyticBlurWorked) {
379 if (!draw_rrect_into_mask(smallRR, &srcM)) { 438 if (!draw_rrect_into_mask(smallRR, &srcM)) {
380 return kFalse_FilterReturn; 439 return kFalse_FilterReturn;
381 } 440 }
382 441
383 SkAutoMaskFreeImage amf(srcM.fImage); 442 SkAutoMaskFreeImage amf(srcM.fImage);
384 443
385 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 444 if (!this->filterMask(&(patch->fCachedMask.fMask), srcM, matrix, &margin )) {
386 return kFalse_FilterReturn; 445 return kFalse_FilterReturn;
387 } 446 }
388 } 447 }
389 448
390 patch->fMask.fBounds.offsetTo(0, 0); 449 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0);
391 patch->fOuterRect = dstM.fBounds; 450 patch->fOuterRect = dstM.fBounds;
392 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; 451 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1;
393 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; 452 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1;
453 if (!cachedBlurMask.fCacheId) {
454 SkBitmap bitmap;
455 bitmap.installMaskPixels(patch->fCachedMask.fMask);
456 patch->fCachedMask.fCacheId = SkBitmapCache::AddAndLock(sigma, rrect, bi tmap);
457 }
458
394 return kTrue_FilterReturn; 459 return kTrue_FilterReturn;
395 } 460 }
396 461
397 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" ); 462 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
398 463
399 SkMaskFilter::FilterReturn 464 SkMaskFilter::FilterReturn
400 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, 465 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
401 const SkMatrix& matrix, 466 const SkMatrix& matrix,
402 const SkIRect& clipBounds, 467 const SkIRect& clipBounds,
403 NinePatch* patch) const { 468 NinePatch* patch) const {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 if (1 == count) { 528 if (1 == count) {
464 innerIR = srcM.fBounds; 529 innerIR = srcM.fBounds;
465 center.set(smallW, smallH); 530 center.set(smallW, smallH);
466 } else { 531 } else {
467 SkASSERT(2 == count); 532 SkASSERT(2 == count);
468 rects[1].roundIn(&innerIR); 533 rects[1].roundIn(&innerIR);
469 center.set(smallW + (innerIR.left() - srcM.fBounds.left()), 534 center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
470 smallH + (innerIR.top() - srcM.fBounds.top())); 535 smallH + (innerIR.top() - srcM.fBounds.top()));
471 } 536 }
472 537
538 SkScalar sigma = this->computeXformedSigma(matrix);
539 SkCachedMask cachedBlurMask;
540 cachedBlurMask.fCacheId = NULL;
541 if (getCachedBlurMask(sigma, count, rects, cachedBlurMask)) {
542 patch->fCachedMask = cachedBlurMask;
543 patch->fOuterRect = dstM.fBounds;
544 patch->fCenter = center;
545 return kTrue_FilterReturn;
546 }
547
473 // +1 so we get a clean, stretchable, center row/col 548 // +1 so we get a clean, stretchable, center row/col
474 smallW += 1; 549 smallW += 1;
475 smallH += 1; 550 smallH += 1;
476 551
477 // we want the inset amounts to be integral, so we don't change any 552 // 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. 553 // fractional phase on the fRight or fBottom of our smallR.
479 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); 554 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
480 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); 555 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
481 if (dx < 0 || dy < 0) { 556 if (dx < 0 || dy < 0) {
482 // we're too small, relative to our blur, to break into nine-patch, 557 // we're too small, relative to our blur, to break into nine-patch,
483 // so we ask to have our normal filterMask() be called. 558 // so we ask to have our normal filterMask() be called.
484 return kUnimplemented_FilterReturn; 559 return kUnimplemented_FilterReturn;
485 } 560 }
486 561
487 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[ 0].bottom() - dy); 562 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) { 563 if (smallR[0].width() < 2 || smallR[0].height() < 2) {
489 return kUnimplemented_FilterReturn; 564 return kUnimplemented_FilterReturn;
490 } 565 }
491 if (2 == count) { 566 if (2 == count) {
492 smallR[1].set(rects[1].left(), rects[1].top(), 567 smallR[1].set(rects[1].left(), rects[1].top(),
493 rects[1].right() - dx, rects[1].bottom() - dy); 568 rects[1].right() - dx, rects[1].bottom() - dy);
494 SkASSERT(!smallR[1].isEmpty()); 569 SkASSERT(!smallR[1].isEmpty());
495 } 570 }
496 571
497 if (count > 1 || !c_analyticBlurNinepatch) { 572 if (count > 1 || !c_analyticBlurNinepatch) {
498 if (!draw_rects_into_mask(smallR, count, &srcM)) { 573 if (!draw_rects_into_mask(smallR, count, &srcM)) {
499 return kFalse_FilterReturn; 574 return kFalse_FilterReturn;
500 } 575 }
501
502 SkAutoMaskFreeImage amf(srcM.fImage); 576 SkAutoMaskFreeImage amf(srcM.fImage);
503 577
504 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 578 if (!this->filterMask(&patch->fCachedMask.fMask, srcM, matrix, &margin)) {
505 return kFalse_FilterReturn; 579 return kFalse_FilterReturn;
506 } 580 }
507 } else { 581 } else {
508 if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, 582 if (!this->filterRectMask(&patch->fCachedMask.fMask, smallR[0], matrix, &margin,
509 SkMask::kComputeBoundsAndRenderImage_CreateMod e)) { 583 SkMask::kComputeBoundsAndRenderImage_CreateMod e)) {
510 return kFalse_FilterReturn; 584 return kFalse_FilterReturn;
511 } 585 }
512 } 586 }
513 patch->fMask.fBounds.offsetTo(0, 0); 587 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0);
514 patch->fOuterRect = dstM.fBounds; 588 patch->fOuterRect = dstM.fBounds;
515 patch->fCenter = center; 589 patch->fCenter = center;
590 if (!cachedBlurMask.fCacheId) {
591 SkBitmap bitmap;
592 bitmap.installMaskPixels(patch->fCachedMask.fMask);
593 patch->fCachedMask.fCacheId = SkBitmapCache::AddAndLock(sigma, count, re cts, bitmap);
594 }
595
516 return kTrue_FilterReturn; 596 return kTrue_FilterReturn;
517 } 597 }
518 598
519 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 599 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
520 SkRect* dst) const { 600 SkRect* dst) const {
521 SkScalar pad = 3.0f * fSigma; 601 SkScalar pad = 3.0f * fSigma;
522 602
523 dst->set(src.fLeft - pad, src.fTop - pad, 603 dst->set(src.fLeft - pad, src.fTop - pad,
524 src.fRight + pad, src.fBottom + pad); 604 src.fRight + pad, src.fBottom + pad);
525 } 605 }
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 } else { 1296 } else {
1217 str->append("None"); 1297 str->append("None");
1218 } 1298 }
1219 str->append("))"); 1299 str->append("))");
1220 } 1300 }
1221 #endif 1301 #endif
1222 1302
1223 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1303 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1224 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1304 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1225 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1305 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« src/core/SkScaledImageCache.h ('K') | « src/effects/SkBlurMask.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698