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

Side by Side Diff: src/core/SkCanvas.cpp

Issue 2225393002: Optimized implementation of quickReject() (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments Created 4 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
« no previous file with comments | « include/core/SkPostConfig.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 * Copyright 2008 The Android Open Source Project 2 * Copyright 2008 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBitmapDevice.h" 8 #include "SkBitmapDevice.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkCanvasPriv.h" 10 #include "SkCanvasPriv.h"
11 #include "SkClipStack.h" 11 #include "SkClipStack.h"
12 #include "SkColorFilter.h" 12 #include "SkColorFilter.h"
13 #include "SkDraw.h" 13 #include "SkDraw.h"
14 #include "SkDrawable.h" 14 #include "SkDrawable.h"
15 #include "SkDrawFilter.h" 15 #include "SkDrawFilter.h"
16 #include "SkDrawLooper.h" 16 #include "SkDrawLooper.h"
17 #include "SkErrorInternals.h" 17 #include "SkErrorInternals.h"
18 #include "SkImage.h" 18 #include "SkImage.h"
19 #include "SkImage_Base.h" 19 #include "SkImage_Base.h"
20 #include "SkImageFilter.h" 20 #include "SkImageFilter.h"
21 #include "SkImageFilterCache.h" 21 #include "SkImageFilterCache.h"
22 #include "SkLatticeIter.h" 22 #include "SkLatticeIter.h"
23 #include "SkMatrixUtils.h" 23 #include "SkMatrixUtils.h"
24 #include "SkMetaData.h" 24 #include "SkMetaData.h"
25 #include "SkNx.h"
25 #include "SkPaintPriv.h" 26 #include "SkPaintPriv.h"
26 #include "SkPatchUtils.h" 27 #include "SkPatchUtils.h"
27 #include "SkPicture.h" 28 #include "SkPicture.h"
28 #include "SkRasterClip.h" 29 #include "SkRasterClip.h"
29 #include "SkReadPixelsRec.h" 30 #include "SkReadPixelsRec.h"
30 #include "SkRRect.h" 31 #include "SkRRect.h"
31 #include "SkSmallAllocator.h" 32 #include "SkSmallAllocator.h"
32 #include "SkSpecialImage.h" 33 #include "SkSpecialImage.h"
33 #include "SkSurface_Base.h" 34 #include "SkSurface_Base.h"
34 #include "SkTextBlob.h" 35 #include "SkTextBlob.h"
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ 626 AutoDrawLooper looper(this, fProps, paint, false, bounds); \
626 while (looper.next(type)) { \ 627 while (looper.next(type)) { \
627 SkDrawIter iter(this); 628 SkDrawIter iter(this);
628 629
629 #define LOOPER_END } 630 #define LOOPER_END }
630 631
631 //////////////////////////////////////////////////////////////////////////// 632 ////////////////////////////////////////////////////////////////////////////
632 633
633 void SkCanvas::resetForNextPicture(const SkIRect& bounds) { 634 void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
634 this->restoreToCount(1); 635 this->restoreToCount(1);
635 fCachedLocalClipBounds.setEmpty();
636 fCachedLocalClipBoundsDirty = true;
637 fClipStack->reset(); 636 fClipStack->reset();
638 fMCRec->reset(bounds); 637 fMCRec->reset(bounds);
639 638
640 // We're peering through a lot of structs here. Only at this scope do we 639 // We're peering through a lot of structs here. Only at this scope do we
641 // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevi ce). 640 // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevi ce).
642 static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.siz e()); 641 static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.siz e());
642 this->setCachedClipDeviceBounds(bounds);
643 fConservativeIsScaleTranslate = true;
643 } 644 }
644 645
645 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { 646 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
646 if (device && device->forceConservativeRasterClip()) { 647 if (device && device->forceConservativeRasterClip()) {
647 flags = InitFlags(flags | kConservativeRasterClip_InitFlag); 648 flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
648 } 649 }
649 // Since init() is only called once by our constructors, it is safe to perfo rm this 650 // Since init() is only called once by our constructors, it is safe to perfo rm this
650 // const-cast. 651 // const-cast.
651 *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativ eRasterClip_InitFlag); 652 *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativ eRasterClip_InitFlag);
652 653
653 fCachedLocalClipBounds.setEmpty();
654 fCachedLocalClipBoundsDirty = true;
655 fAllowSoftClip = true; 654 fAllowSoftClip = true;
656 fAllowSimplifyClip = false; 655 fAllowSimplifyClip = false;
657 fDeviceCMDirty = true; 656 fDeviceCMDirty = true;
658 fSaveCount = 1; 657 fSaveCount = 1;
659 fMetaData = nullptr; 658 fMetaData = nullptr;
660 #ifdef SK_EXPERIMENTAL_SHADOWING 659 #ifdef SK_EXPERIMENTAL_SHADOWING
661 fLights = nullptr; 660 fLights = nullptr;
662 #endif 661 #endif
663 662
664 fClipStack.reset(new SkClipStack); 663 fClipStack.reset(new SkClipStack);
665 664
666 fMCRec = (MCRec*)fMCStack.push_back(); 665 fMCRec = (MCRec*)fMCStack.push_back();
667 new (fMCRec) MCRec(fConservativeRasterClip); 666 new (fMCRec) MCRec(fConservativeRasterClip);
668 667
669 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); 668 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
670 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; 669 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
671 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip, 670 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip,
672 fMCRec->fMatrix); 671 fMCRec->fMatrix);
673 672
674 fMCRec->fTopLayer = fMCRec->fLayer; 673 fMCRec->fTopLayer = fMCRec->fLayer;
675 674
676 fSurfaceBase = nullptr; 675 fSurfaceBase = nullptr;
677 676
678 if (device) { 677 if (device) {
679 // The root device and the canvas should always have the same pixel geom etry 678 // The root device and the canvas should always have the same pixel geom etry
680 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( )); 679 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( ));
681 fMCRec->fLayer->fDevice = SkRef(device); 680 fMCRec->fLayer->fDevice = SkRef(device);
682 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); 681 fMCRec->fRasterClip.setRect(device->getGlobalBounds());
682 this->setCachedClipDeviceBounds(device->getGlobalBounds());
683 fConservativeIsScaleTranslate = true;
683 } 684 }
685
684 return device; 686 return device;
685 } 687 }
686 688
687 SkCanvas::SkCanvas() 689 SkCanvas::SkCanvas()
688 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 690 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
689 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 691 , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
690 , fConservativeRasterClip(false) 692 , fConservativeRasterClip(false)
691 { 693 {
692 inc_canvas(); 694 inc_canvas();
693 695
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 } 1090 }
1089 SkIRect ir; 1091 SkIRect ir;
1090 if (bounds) { 1092 if (bounds) {
1091 SkRect r; 1093 SkRect r;
1092 1094
1093 ctm.mapRect(&r, *bounds); 1095 ctm.mapRect(&r, *bounds);
1094 r.roundOut(&ir); 1096 r.roundOut(&ir);
1095 // early exit if the layer's bounds are clipped out 1097 // early exit if the layer's bounds are clipped out
1096 if (!ir.intersect(clipBounds)) { 1098 if (!ir.intersect(clipBounds)) {
1097 if (BoundsAffectsClip(saveLayerFlags)) { 1099 if (BoundsAffectsClip(saveLayerFlags)) {
1098 fCachedLocalClipBoundsDirty = true;
1099 fMCRec->fRasterClip.setEmpty(); 1100 fMCRec->fRasterClip.setEmpty();
1101 fDeviceClipBounds.setEmpty();
1100 } 1102 }
1101 return false; 1103 return false;
1102 } 1104 }
1103 } else { // no user bounds, so just use the clip 1105 } else { // no user bounds, so just use the clip
1104 ir = clipBounds; 1106 ir = clipBounds;
1105 } 1107 }
1106 SkASSERT(!ir.isEmpty()); 1108 SkASSERT(!ir.isEmpty());
1107 1109
1108 if (BoundsAffectsClip(saveLayerFlags)) { 1110 if (BoundsAffectsClip(saveLayerFlags)) {
1109 // Simplify the current clips since they will be applied properly during restore() 1111 // Simplify the current clips since they will be applied properly during restore()
1110 fCachedLocalClipBoundsDirty = true;
1111 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op); 1112 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1112 fMCRec->fRasterClip.setRect(ir); 1113 fMCRec->fRasterClip.setRect(ir);
1114 this->setCachedClipDeviceBounds(ir);
1113 } 1115 }
1114 1116
1115 if (intersection) { 1117 if (intersection) {
1116 *intersection = ir; 1118 *intersection = ir;
1117 } 1119 }
1118 return true; 1120 return true;
1119 } 1121 }
1120 1122
1121 1123
1122 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) { 1124 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 SkPaint tmpPaint; 1296 SkPaint tmpPaint;
1295 tmpPaint.setAlpha(alpha); 1297 tmpPaint.setAlpha(alpha);
1296 return this->saveLayer(bounds, &tmpPaint); 1298 return this->saveLayer(bounds, &tmpPaint);
1297 } 1299 }
1298 } 1300 }
1299 1301
1300 void SkCanvas::internalRestore() { 1302 void SkCanvas::internalRestore() {
1301 SkASSERT(fMCStack.count() != 0); 1303 SkASSERT(fMCStack.count() != 0);
1302 1304
1303 fDeviceCMDirty = true; 1305 fDeviceCMDirty = true;
1304 fCachedLocalClipBoundsDirty = true;
1305 1306
1306 fClipStack->restore(); 1307 fClipStack->restore();
1307 1308
1308 // reserve our layer (if any) 1309 // reserve our layer (if any)
1309 DeviceCM* layer = fMCRec->fLayer; // may be null 1310 DeviceCM* layer = fMCRec->fLayer; // may be null
1310 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1311 // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1311 fMCRec->fLayer = nullptr; 1312 fMCRec->fLayer = nullptr;
1312 1313
1313 // now do the normal restore() 1314 // now do the normal restore()
1314 fMCRec->~MCRec(); // balanced in save() 1315 fMCRec->~MCRec(); // balanced in save()
(...skipping 13 matching lines...) Expand all
1328 // reset this, since internalDrawDevice will have set it to true 1329 // reset this, since internalDrawDevice will have set it to true
1329 fDeviceCMDirty = true; 1330 fDeviceCMDirty = true;
1330 delete layer; 1331 delete layer;
1331 } else { 1332 } else {
1332 // we're at the root 1333 // we're at the root
1333 SkASSERT(layer == (void*)fDeviceCMStorage); 1334 SkASSERT(layer == (void*)fDeviceCMStorage);
1334 layer->~DeviceCM(); 1335 layer->~DeviceCM();
1335 // no need to update fMCRec, 'cause we're killing the canvas 1336 // no need to update fMCRec, 'cause we're killing the canvas
1336 } 1337 }
1337 } 1338 }
1339
1340 if (fMCRec) {
1341 fConservativeIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1342 this->setCachedClipDeviceBounds(fMCRec->fRasterClip.getBounds());
1343 }
1338 } 1344 }
1339 1345
1340 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) { 1346 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) {
1341 if (nullptr == props) { 1347 if (nullptr == props) {
1342 props = &fProps; 1348 props = &fProps;
1343 } 1349 }
1344 return this->onNewSurface(info, *props); 1350 return this->onNewSurface(info, *props);
1345 } 1351 }
1346 1352
1347 sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurface Props& props) { 1353 sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurface Props& props) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1482 this->concat(m); 1488 this->concat(m);
1483 } 1489 }
1484 1490
1485 void SkCanvas::concat(const SkMatrix& matrix) { 1491 void SkCanvas::concat(const SkMatrix& matrix) {
1486 if (matrix.isIdentity()) { 1492 if (matrix.isIdentity()) {
1487 return; 1493 return;
1488 } 1494 }
1489 1495
1490 this->checkForDeferredSave(); 1496 this->checkForDeferredSave();
1491 fDeviceCMDirty = true; 1497 fDeviceCMDirty = true;
1492 fCachedLocalClipBoundsDirty = true;
1493 fMCRec->fMatrix.preConcat(matrix); 1498 fMCRec->fMatrix.preConcat(matrix);
1494 1499
1500 // We may miss some rare cases here. Ex: rotate 45 then -45. But being dat a
1501 // independ of preConcat() may allow us to go faster.
1502 fConservativeIsScaleTranslate = fConservativeIsScaleTranslate && matrix.isSc aleTranslate();
1495 this->didConcat(matrix); 1503 this->didConcat(matrix);
1496 } 1504 }
1497 1505
1498 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) { 1506 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1499 fDeviceCMDirty = true; 1507 fDeviceCMDirty = true;
1500 fCachedLocalClipBoundsDirty = true;
1501 fMCRec->fMatrix = matrix; 1508 fMCRec->fMatrix = matrix;
1502 } 1509 }
1503 1510
1504 void SkCanvas::setMatrix(const SkMatrix& matrix) { 1511 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1505 this->checkForDeferredSave(); 1512 this->checkForDeferredSave();
1506 this->internalSetMatrix(matrix); 1513 this->internalSetMatrix(matrix);
1514 fConservativeIsScaleTranslate = matrix.isScaleTranslate();
1507 this->didSetMatrix(matrix); 1515 this->didSetMatrix(matrix);
1508 } 1516 }
1509 1517
1510 void SkCanvas::resetMatrix() { 1518 void SkCanvas::resetMatrix() {
1511 this->setMatrix(SkMatrix::I()); 1519 this->setMatrix(SkMatrix::I());
1512 } 1520 }
1513 1521
1514 #ifdef SK_EXPERIMENTAL_SHADOWING 1522 #ifdef SK_EXPERIMENTAL_SHADOWING
1515 void SkCanvas::translateZ(SkScalar z) { 1523 void SkCanvas::translateZ(SkScalar z) {
1516 this->checkForDeferredSave(); 1524 this->checkForDeferredSave();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 rect.left(), rect.top(), rect.right(), rect.bottom()); 1605 rect.left(), rect.top(), rect.right(), rect.bottom());
1598 #endif 1606 #endif
1599 return; 1607 return;
1600 } 1608 }
1601 } 1609 }
1602 #endif 1610 #endif
1603 1611
1604 AutoValidateClip avc(this); 1612 AutoValidateClip avc(this);
1605 1613
1606 fDeviceCMDirty = true; 1614 fDeviceCMDirty = true;
1607 fCachedLocalClipBoundsDirty = true;
1608 1615
1609 if (isScaleTrans) { 1616 if (isScaleTrans) {
1610 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle; 1617 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1611 fClipStack->clipDevRect(devR, op, isAA); 1618 fClipStack->clipDevRect(devR, op, isAA);
1612 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA); 1619 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA);
1613 } else { 1620 } else {
1614 // since we're rotated or some such thing, we convert the rect to a path 1621 // since we're rotated or some such thing, we convert the rect to a path
1615 // and clip against that, since it can handle any matrix. However, to 1622 // and clip against that, since it can handle any matrix. However, to
1616 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1623 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1617 // we explicitly call "our" version of clipPath. 1624 // we explicitly call "our" version of clipPath.
1618 SkPath path; 1625 SkPath path;
1619 1626
1620 path.addRect(rect); 1627 path.addRect(rect);
1621 this->SkCanvas::onClipPath(path, op, edgeStyle); 1628 this->SkCanvas::onClipPath(path, op, edgeStyle);
1622 } 1629 }
1630
1631 this->setCachedClipDeviceBounds(fMCRec->fRasterClip.getBounds());
1623 } 1632 }
1624 1633
1625 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1634 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1626 this->checkForDeferredSave(); 1635 this->checkForDeferredSave();
1627 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1636 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1628 if (rrect.isRect()) { 1637 if (rrect.isRect()) {
1629 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1638 this->onClipRect(rrect.getBounds(), op, edgeStyle);
1630 } else { 1639 } else {
1631 this->onClipRRect(rrect, op, edgeStyle); 1640 this->onClipRRect(rrect, op, edgeStyle);
1632 } 1641 }
1633 } 1642 }
1634 1643
1635 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1644 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1636 SkRRect transformedRRect; 1645 SkRRect transformedRRect;
1637 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1646 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1638 AutoValidateClip avc(this); 1647 AutoValidateClip avc(this);
1639 1648
1640 fDeviceCMDirty = true; 1649 fDeviceCMDirty = true;
1641 fCachedLocalClipBoundsDirty = true;
1642 if (!fAllowSoftClip) { 1650 if (!fAllowSoftClip) {
1643 edgeStyle = kHard_ClipEdgeStyle; 1651 edgeStyle = kHard_ClipEdgeStyle;
1644 } 1652 }
1645 1653
1646 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed geStyle); 1654 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed geStyle);
1647 1655
1648 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op, 1656 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op,
1649 kSoft_ClipEdgeStyle == edgeStyle); 1657 kSoft_ClipEdgeStyle == edgeStyle);
1658 this->setCachedClipDeviceBounds(fMCRec->fRasterClip.getBounds());
1650 return; 1659 return;
1651 } 1660 }
1652 1661
1653 SkPath path; 1662 SkPath path;
1654 path.addRRect(rrect); 1663 path.addRRect(rrect);
1655 // call the non-virtual version 1664 // call the non-virtual version
1656 this->SkCanvas::onClipPath(path, op, edgeStyle); 1665 this->SkCanvas::onClipPath(path, op, edgeStyle);
1657 } 1666 }
1658 1667
1659 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1668 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 fClipStack->clipEmpty(); 1704 fClipStack->clipEmpty();
1696 (void)fMCRec->fRasterClip.setEmpty(); 1705 (void)fMCRec->fRasterClip.setEmpty();
1697 return; 1706 return;
1698 } 1707 }
1699 } 1708 }
1700 #endif 1709 #endif
1701 1710
1702 AutoValidateClip avc(this); 1711 AutoValidateClip avc(this);
1703 1712
1704 fDeviceCMDirty = true; 1713 fDeviceCMDirty = true;
1705 fCachedLocalClipBoundsDirty = true;
1706 if (!fAllowSoftClip) { 1714 if (!fAllowSoftClip) {
1707 edgeStyle = kHard_ClipEdgeStyle; 1715 edgeStyle = kHard_ClipEdgeStyle;
1708 } 1716 }
1709 1717
1710 SkPath devPath; 1718 SkPath devPath;
1711 path.transform(fMCRec->fMatrix, &devPath); 1719 path.transform(fMCRec->fMatrix, &devPath);
1712 1720
1713 // Check if the transfomation, or the original path itself 1721 // Check if the transfomation, or the original path itself
1714 // made us empty. Note this can also happen if we contained NaN 1722 // made us empty. Note this can also happen if we contained NaN
1715 // values. computing the bounds detects this, and will set our 1723 // values. computing the bounds detects this, and will set our
(...skipping 10 matching lines...) Expand all
1726 if (fAllowSimplifyClip) { 1734 if (fAllowSimplifyClip) {
1727 bool clipIsAA = getClipStack()->asPath(&devPath); 1735 bool clipIsAA = getClipStack()->asPath(&devPath);
1728 if (clipIsAA) { 1736 if (clipIsAA) {
1729 edgeStyle = kSoft_ClipEdgeStyle; 1737 edgeStyle = kSoft_ClipEdgeStyle;
1730 } 1738 }
1731 1739
1732 op = SkRegion::kReplace_Op; 1740 op = SkRegion::kReplace_Op;
1733 } 1741 }
1734 1742
1735 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle); 1743 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle);
1744 this->setCachedClipDeviceBounds(fMCRec->fRasterClip.getBounds());
1736 } 1745 }
1737 1746
1738 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1747 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1739 this->checkForDeferredSave(); 1748 this->checkForDeferredSave();
1740 this->onClipRegion(rgn, op); 1749 this->onClipRegion(rgn, op);
1741 } 1750 }
1742 1751
1743 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1752 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1744 AutoValidateClip avc(this); 1753 AutoValidateClip avc(this);
1745 1754
1746 fDeviceCMDirty = true; 1755 fDeviceCMDirty = true;
1747 fCachedLocalClipBoundsDirty = true;
1748 1756
1749 // todo: signal fClipStack that we have a region, and therefore (I guess) 1757 // todo: signal fClipStack that we have a region, and therefore (I guess)
1750 // we have to ignore it, and use the region directly? 1758 // we have to ignore it, and use the region directly?
1751 fClipStack->clipDevRect(rgn.getBounds(), op); 1759 fClipStack->clipDevRect(rgn.getBounds(), op);
1752 1760
1753 fMCRec->fRasterClip.op(rgn, op); 1761 fMCRec->fRasterClip.op(rgn, op);
1762 this->setCachedClipDeviceBounds(fMCRec->fRasterClip.getBounds());
1754 } 1763 }
1755 1764
1756 #ifdef SK_DEBUG 1765 #ifdef SK_DEBUG
1757 void SkCanvas::validateClip() const { 1766 void SkCanvas::validateClip() const {
1758 // construct clipRgn from the clipstack 1767 // construct clipRgn from the clipstack
1759 const SkBaseDevice* device = this->getDevice(); 1768 const SkBaseDevice* device = this->getDevice();
1760 if (!device) { 1769 if (!device) {
1761 SkASSERT(this->isClipEmpty()); 1770 SkASSERT(this->isClipEmpty());
1762 return; 1771 return;
1763 } 1772 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1800 /////////////////////////////////////////////////////////////////////////////// 1809 ///////////////////////////////////////////////////////////////////////////////
1801 1810
1802 bool SkCanvas::isClipEmpty() const { 1811 bool SkCanvas::isClipEmpty() const {
1803 return fMCRec->fRasterClip.isEmpty(); 1812 return fMCRec->fRasterClip.isEmpty();
1804 } 1813 }
1805 1814
1806 bool SkCanvas::isClipRect() const { 1815 bool SkCanvas::isClipRect() const {
1807 return fMCRec->fRasterClip.isRect(); 1816 return fMCRec->fRasterClip.isRect();
1808 } 1817 }
1809 1818
1810 bool SkCanvas::quickReject(const SkRect& rect) const { 1819 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1811 if (!rect.isFinite()) 1820 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1812 return true; 1821 __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1822 __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1823 __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1824 return 0xF != _mm_movemask_ps(mask);
1825 #elif defined(SK_ARM_HAS_NEON)
1826 float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1827 float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1828 uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1829 return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1830 #else
1831 SkRect devRectAsRect;
1832 SkRect devClipAsRect;
1833 devRect.store(&devRectAsRect.fLeft);
1834 devClip.store(&devClipAsRect.fLeft);
1835 return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1836 #endif
1837 }
1813 1838
1814 if (fMCRec->fRasterClip.isEmpty()) { 1839 // It's important for this function to not be inlined. Otherwise the compiler w ill share code
1815 return true; 1840 // between the fast path and the slow path, resulting in two slow paths.
1841 static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRe ct& deviceClip,
1842 const SkMatrix& matrix) {
1843 SkRect deviceRect;
1844 matrix.mapRect(&deviceRect, src);
1845 return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1846 }
1847
1848 bool SkCanvas::quickReject(const SkRect& src) const {
reed1 2016/08/11 18:36:28 SkASSERT(compute_float_from_rasterclip_bounds == f
msarett 2016/08/11 20:15:16 Done.
1849 if (!fConservativeIsScaleTranslate) {
1850 return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1816 } 1851 }
1817 1852
1818 if (fMCRec->fMatrix.hasPerspective()) { 1853 // We inline the implementation of mapScaleTranslate() for the fast path.
1819 SkRect dst; 1854 float sx = fMCRec->fMatrix.getScaleX();
1820 fMCRec->fMatrix.mapRect(&dst, rect); 1855 float sy = fMCRec->fMatrix.getScaleY();
1821 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBound s()); 1856 float tx = fMCRec->fMatrix.getTranslateX();
1822 } else { 1857 float ty = fMCRec->fMatrix.getTranslateY();
1823 const SkRect& clipR = this->getLocalClipBounds(); 1858 Sk4f scale(sx, sy, sx, sy);
1859 Sk4f trans(tx, ty, tx, ty);
1824 1860
1825 // for speed, do the most likely reject compares first 1861 // Apply matrix.
1826 // TODO: should we use | instead, or compare all 4 at once? 1862 Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1827 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1863
1828 return true; 1864 // Make sure left < right, top < bottom.
1829 } 1865 Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1830 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1866 Sk4f min = Sk4f::Min(ltrb, rblt);
1831 return true; 1867 Sk4f max = Sk4f::Max(ltrb, rblt);
1832 } 1868 // We can extract either pair [0,1] or [2,3] from min and max and be correct , but on
1833 return false; 1869 // ARM this sequence generates the fastest (a single instruction).
1834 } 1870 Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1871
1872 // Check if the device rect is NaN or outside the clip.
1873 return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1835 } 1874 }
1836 1875
1837 bool SkCanvas::quickReject(const SkPath& path) const { 1876 bool SkCanvas::quickReject(const SkPath& path) const {
1838 return path.isEmpty() || this->quickReject(path.getBounds()); 1877 return path.isEmpty() || this->quickReject(path.getBounds());
1839 } 1878 }
1840 1879
1841 bool SkCanvas::getClipBounds(SkRect* bounds) const { 1880 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1842 SkIRect ibounds; 1881 SkIRect ibounds;
1843 if (!this->getClipDeviceBounds(&ibounds)) { 1882 if (!this->getClipDeviceBounds(&ibounds)) {
1844 return false; 1883 return false;
(...skipping 28 matching lines...) Expand all
1873 } 1912 }
1874 return false; 1913 return false;
1875 } 1914 }
1876 1915
1877 if (bounds) { 1916 if (bounds) {
1878 *bounds = clip.getBounds(); 1917 *bounds = clip.getBounds();
1879 } 1918 }
1880 return true; 1919 return true;
1881 } 1920 }
1882 1921
1922 void SkCanvas::setCachedClipDeviceBounds(const SkIRect& bounds) {
1923 // Expand bounds out by 1 in case we are anti-aliasing. We store the
1924 // bounds as floats to enable a faster quick reject implementation.
1925 SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&fDevice ClipBounds.fLeft);
1926 }
1927
1883 const SkMatrix& SkCanvas::getTotalMatrix() const { 1928 const SkMatrix& SkCanvas::getTotalMatrix() const {
1884 return fMCRec->fMatrix; 1929 return fMCRec->fMatrix;
1885 } 1930 }
1886 1931
1887 const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1932 const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1888 return fMCRec->fRasterClip.forceGetBW(); 1933 return fMCRec->fRasterClip.forceGetBW();
1889 } 1934 }
1890 1935
1891 GrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() { 1936 GrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() {
1892 SkBaseDevice* dev = this->getTopDevice(); 1937 SkBaseDevice* dev = this->getTopDevice();
(...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after
3168 3213
3169 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3214 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3170 fCanvas->restoreToCount(fSaveCount); 3215 fCanvas->restoreToCount(fSaveCount);
3171 } 3216 }
3172 3217
3173 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 3218 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
3174 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) { 3219 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) {
3175 return this->makeSurface(info, props).release(); 3220 return this->makeSurface(info, props).release();
3176 } 3221 }
3177 #endif 3222 #endif
OLDNEW
« no previous file with comments | « include/core/SkPostConfig.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698