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

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

Issue 894693003: Add refcnting to SkClipStack on SkCanvas (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: feedback inc Created 5 years, 10 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/gpu/GrContext.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | 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 "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkCanvasDrawable.h" 9 #include "SkCanvasDrawable.h"
10 #include "SkCanvasPriv.h" 10 #include "SkCanvasPriv.h"
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 } 225 }
226 }; 226 };
227 227
228 class SkDrawIter : public SkDraw { 228 class SkDrawIter : public SkDraw {
229 public: 229 public:
230 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 230 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
231 canvas = canvas->canvasForDrawIter(); 231 canvas = canvas->canvasForDrawIter();
232 fCanvas = canvas; 232 fCanvas = canvas;
233 canvas->updateDeviceCMCache(); 233 canvas->updateDeviceCMCache();
234 234
235 fClipStack = &canvas->fClipStack; 235 fClipStack = canvas->fClipStack.get();
236 fCurrLayer = canvas->fMCRec->fTopLayer; 236 fCurrLayer = canvas->fMCRec->fTopLayer;
237 fSkipEmptyClips = skipEmptyClips; 237 fSkipEmptyClips = skipEmptyClips;
238 } 238 }
239 239
240 bool next() { 240 bool next() {
241 // skip over recs with empty clips 241 // skip over recs with empty clips
242 if (fSkipEmptyClips) { 242 if (fSkipEmptyClips) {
243 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 243 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
244 fCurrLayer = fCurrLayer->fNext; 244 fCurrLayer = fCurrLayer->fNext;
245 } 245 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 fMetaData = NULL; 435 fMetaData = NULL;
436 436
437 fMCRec = (MCRec*)fMCStack.push_back(); 437 fMCRec = (MCRec*)fMCStack.push_back();
438 new (fMCRec) MCRec(fConservativeRasterClip); 438 new (fMCRec) MCRec(fConservativeRasterClip);
439 439
440 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative RasterClip)); 440 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative RasterClip));
441 fMCRec->fTopLayer = fMCRec->fLayer; 441 fMCRec->fTopLayer = fMCRec->fLayer;
442 442
443 fSurfaceBase = NULL; 443 fSurfaceBase = NULL;
444 444
445 fClipStack.reset(SkNEW(SkClipStack));
446
445 if (device) { 447 if (device) {
446 device->initForRootLayer(fProps.pixelGeometry()); 448 device->initForRootLayer(fProps.pixelGeometry());
447 if (device->forceConservativeRasterClip()) { 449 if (device->forceConservativeRasterClip()) {
448 fConservativeRasterClip = true; 450 fConservativeRasterClip = true;
449 } 451 }
450 device->onAttachToCanvas(this); 452 device->onAttachToCanvas(this);
451 fMCRec->fLayer->fDevice = SkRef(device); 453 fMCRec->fLayer->fDevice = SkRef(device);
452 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); 454 fMCRec->fRasterClip.setRect(device->getGlobalBounds());
453 } 455 }
454 return device; 456 return device;
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 783
782 ////////////////////////////////////////////////////////////////////////////// 784 //////////////////////////////////////////////////////////////////////////////
783 785
784 void SkCanvas::updateDeviceCMCache() { 786 void SkCanvas::updateDeviceCMCache() {
785 if (fDeviceCMDirty) { 787 if (fDeviceCMDirty) {
786 const SkMatrix& totalMatrix = this->getTotalMatrix(); 788 const SkMatrix& totalMatrix = this->getTotalMatrix();
787 const SkRasterClip& totalClip = fMCRec->fRasterClip; 789 const SkRasterClip& totalClip = fMCRec->fRasterClip;
788 DeviceCM* layer = fMCRec->fTopLayer; 790 DeviceCM* layer = fMCRec->fTopLayer;
789 791
790 if (NULL == layer->fNext) { // only one layer 792 if (NULL == layer->fNext) { // only one layer
791 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 793 layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
792 } else { 794 } else {
793 SkRasterClip clip(totalClip); 795 SkRasterClip clip(totalClip);
794 do { 796 do {
795 layer->updateMC(totalMatrix, clip, fClipStack, &clip); 797 layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
796 } while ((layer = layer->fNext) != NULL); 798 } while ((layer = layer->fNext) != NULL);
797 } 799 }
798 fDeviceCMDirty = false; 800 fDeviceCMDirty = false;
799 } 801 }
800 } 802 }
801 803
802 /////////////////////////////////////////////////////////////////////////////// 804 ///////////////////////////////////////////////////////////////////////////////
803 805
804 void SkCanvas::checkForDeferredSave() { 806 void SkCanvas::checkForDeferredSave() {
805 if (fMCRec->fDeferredSaveCount > 0) { 807 if (fMCRec->fDeferredSaveCount > 0) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 for (int i = 0; i < n; ++i) { 864 for (int i = 0; i < n; ++i) {
863 this->restore(); 865 this->restore();
864 } 866 }
865 } 867 }
866 868
867 void SkCanvas::internalSave() { 869 void SkCanvas::internalSave() {
868 MCRec* newTop = (MCRec*)fMCStack.push_back(); 870 MCRec* newTop = (MCRec*)fMCStack.push_back();
869 new (newTop) MCRec(*fMCRec); // balanced in restore() 871 new (newTop) MCRec(*fMCRec); // balanced in restore()
870 fMCRec = newTop; 872 fMCRec = newTop;
871 873
872 fClipStack.save(); 874 fClipStack->save();
873 } 875 }
874 876
875 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 877 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
876 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 878 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
877 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 879 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
878 #else 880 #else
879 return true; 881 return true;
880 #endif 882 #endif
881 } 883 }
882 884
(...skipping 21 matching lines...) Expand all
904 if (bounds_affects_clip(flags)) { 906 if (bounds_affects_clip(flags)) {
905 fMCRec->fRasterClip.setEmpty(); 907 fMCRec->fRasterClip.setEmpty();
906 } 908 }
907 return false; 909 return false;
908 } 910 }
909 } else { // no user bounds, so just use the clip 911 } else { // no user bounds, so just use the clip
910 ir = clipBounds; 912 ir = clipBounds;
911 } 913 }
912 914
913 if (bounds_affects_clip(flags)) { 915 if (bounds_affects_clip(flags)) {
914 fClipStack.clipDevRect(ir, op); 916 fClipStack->clipDevRect(ir, op);
915 // early exit if the clip is now empty 917 // early exit if the clip is now empty
916 if (!fMCRec->fRasterClip.op(ir, op)) { 918 if (!fMCRec->fRasterClip.op(ir, op)) {
917 return false; 919 return false;
918 } 920 }
919 } 921 }
920 922
921 if (intersection) { 923 if (intersection) {
922 *intersection = ir; 924 *intersection = ir;
923 } 925 }
924 return true; 926 return true;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 return this->saveLayer(bounds, &tmpPaint, flags); 1028 return this->saveLayer(bounds, &tmpPaint, flags);
1027 } 1029 }
1028 } 1030 }
1029 1031
1030 void SkCanvas::internalRestore() { 1032 void SkCanvas::internalRestore() {
1031 SkASSERT(fMCStack.count() != 0); 1033 SkASSERT(fMCStack.count() != 0);
1032 1034
1033 fDeviceCMDirty = true; 1035 fDeviceCMDirty = true;
1034 fCachedLocalClipBoundsDirty = true; 1036 fCachedLocalClipBoundsDirty = true;
1035 1037
1036 fClipStack.restore(); 1038 fClipStack->restore();
1037 1039
1038 // reserve our layer (if any) 1040 // reserve our layer (if any)
1039 DeviceCM* layer = fMCRec->fLayer; // may be null 1041 DeviceCM* layer = fMCRec->fLayer; // may be null
1040 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1042 // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1041 fMCRec->fLayer = NULL; 1043 fMCRec->fLayer = NULL;
1042 1044
1043 // now do the normal restore() 1045 // now do the normal restore()
1044 fMCRec->~MCRec(); // balanced in save() 1046 fMCRec->~MCRec(); // balanced in save()
1045 fMCStack.pop_back(); 1047 fMCStack.pop_back();
1046 fMCRec = (MCRec*)fMCStack.back(); 1048 fMCRec = (MCRec*)fMCStack.back();
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 } 1333 }
1332 1334
1333 if (fMCRec->fMatrix.rectStaysRect()) { 1335 if (fMCRec->fMatrix.rectStaysRect()) {
1334 // for these simpler matrices, we can stay a rect even after applying 1336 // for these simpler matrices, we can stay a rect even after applying
1335 // the matrix. This means we don't have to a) make a path, and b) tell 1337 // the matrix. This means we don't have to a) make a path, and b) tell
1336 // the region code to scan-convert the path, only to discover that it 1338 // the region code to scan-convert the path, only to discover that it
1337 // is really just a rect. 1339 // is really just a rect.
1338 SkRect r; 1340 SkRect r;
1339 1341
1340 fMCRec->fMatrix.mapRect(&r, rect); 1342 fMCRec->fMatrix.mapRect(&r, rect);
1341 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1343 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1342 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt yle == edgeStyle); 1344 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt yle == edgeStyle);
1343 } else { 1345 } else {
1344 // since we're rotated or some such thing, we convert the rect to a path 1346 // since we're rotated or some such thing, we convert the rect to a path
1345 // and clip against that, since it can handle any matrix. However, to 1347 // and clip against that, since it can handle any matrix. However, to
1346 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1348 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1347 // we explicitly call "our" version of clipPath. 1349 // we explicitly call "our" version of clipPath.
1348 SkPath path; 1350 SkPath path;
1349 1351
1350 path.addRect(rect); 1352 path.addRect(rect);
1351 this->SkCanvas::onClipPath(path, op, edgeStyle); 1353 this->SkCanvas::onClipPath(path, op, edgeStyle);
(...skipping 19 matching lines...) Expand all
1371 SkRRect transformedRRect; 1373 SkRRect transformedRRect;
1372 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1374 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1373 AutoValidateClip avc(this); 1375 AutoValidateClip avc(this);
1374 1376
1375 fDeviceCMDirty = true; 1377 fDeviceCMDirty = true;
1376 fCachedLocalClipBoundsDirty = true; 1378 fCachedLocalClipBoundsDirty = true;
1377 if (!fAllowSoftClip) { 1379 if (!fAllowSoftClip) {
1378 edgeStyle = kHard_ClipEdgeStyle; 1380 edgeStyle = kHard_ClipEdgeStyle;
1379 } 1381 }
1380 1382
1381 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg eStyle); 1383 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed geStyle);
1382 1384
1383 SkPath devPath; 1385 SkPath devPath;
1384 devPath.addRRect(transformedRRect); 1386 devPath.addRRect(transformedRRect);
1385 1387
1386 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeS tyle == edgeStyle); 1388 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeS tyle == edgeStyle);
1387 return; 1389 return;
1388 } 1390 }
1389 1391
1390 SkPath path; 1392 SkPath path;
1391 path.addRRect(rrect); 1393 path.addRRect(rrect);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1436 // made us empty. Note this can also happen if we contained NaN 1438 // made us empty. Note this can also happen if we contained NaN
1437 // values. computing the bounds detects this, and will set our 1439 // values. computing the bounds detects this, and will set our
1438 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1440 // bounds to empty if that is the case. (see SkRect::set(pts, count))
1439 if (devPath.getBounds().isEmpty()) { 1441 if (devPath.getBounds().isEmpty()) {
1440 // resetting the path will remove any NaN or other wanky values 1442 // resetting the path will remove any NaN or other wanky values
1441 // that might upset our scan converter. 1443 // that might upset our scan converter.
1442 devPath.reset(); 1444 devPath.reset();
1443 } 1445 }
1444 1446
1445 // if we called path.swap() we could avoid a deep copy of this path 1447 // if we called path.swap() we could avoid a deep copy of this path
1446 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1448 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1447 1449
1448 if (fAllowSimplifyClip) { 1450 if (fAllowSimplifyClip) {
1449 bool clipIsAA = getClipStack()->asPath(&devPath); 1451 bool clipIsAA = getClipStack()->asPath(&devPath);
1450 if (clipIsAA) { 1452 if (clipIsAA) {
1451 edgeStyle = kSoft_ClipEdgeStyle; 1453 edgeStyle = kSoft_ClipEdgeStyle;
1452 } 1454 }
1453 1455
1454 op = SkRegion::kReplace_Op; 1456 op = SkRegion::kReplace_Op;
1455 } 1457 }
1456 1458
1457 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); 1459 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1458 } 1460 }
1459 1461
1460 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1462 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1461 this->checkForDeferredSave(); 1463 this->checkForDeferredSave();
1462 this->onClipRegion(rgn, op); 1464 this->onClipRegion(rgn, op);
1463 } 1465 }
1464 1466
1465 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1467 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1466 AutoValidateClip avc(this); 1468 AutoValidateClip avc(this);
1467 1469
1468 fDeviceCMDirty = true; 1470 fDeviceCMDirty = true;
1469 fCachedLocalClipBoundsDirty = true; 1471 fCachedLocalClipBoundsDirty = true;
1470 1472
1471 // todo: signal fClipStack that we have a region, and therefore (I guess) 1473 // todo: signal fClipStack that we have a region, and therefore (I guess)
1472 // we have to ignore it, and use the region directly? 1474 // we have to ignore it, and use the region directly?
1473 fClipStack.clipDevRect(rgn.getBounds(), op); 1475 fClipStack->clipDevRect(rgn.getBounds(), op);
1474 1476
1475 fMCRec->fRasterClip.op(rgn, op); 1477 fMCRec->fRasterClip.op(rgn, op);
1476 } 1478 }
1477 1479
1478 #ifdef SK_DEBUG 1480 #ifdef SK_DEBUG
1479 void SkCanvas::validateClip() const { 1481 void SkCanvas::validateClip() const {
1480 // construct clipRgn from the clipstack 1482 // construct clipRgn from the clipstack
1481 const SkBaseDevice* device = this->getDevice(); 1483 const SkBaseDevice* device = this->getDevice();
1482 if (!device) { 1484 if (!device) {
1483 SkASSERT(this->isClipEmpty()); 1485 SkASSERT(this->isClipEmpty());
1484 return; 1486 return;
1485 } 1487 }
1486 1488
1487 SkIRect ir; 1489 SkIRect ir;
1488 ir.set(0, 0, device->width(), device->height()); 1490 ir.set(0, 0, device->width(), device->height());
1489 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1491 SkRasterClip tmpClip(ir, fConservativeRasterClip);
1490 1492
1491 SkClipStack::B2TIter iter(fClipStack); 1493 SkClipStack::B2TIter iter(*fClipStack);
1492 const SkClipStack::Element* element; 1494 const SkClipStack::Element* element;
1493 while ((element = iter.next()) != NULL) { 1495 while ((element = iter.next()) != NULL) {
1494 switch (element->getType()) { 1496 switch (element->getType()) {
1495 case SkClipStack::Element::kRect_Type: 1497 case SkClipStack::Element::kRect_Type:
1496 element->getRect().round(&ir); 1498 element->getRect().round(&ir);
1497 tmpClip.op(ir, element->getOp()); 1499 tmpClip.op(ir, element->getOp());
1498 break; 1500 break;
1499 case SkClipStack::Element::kEmpty_Type: 1501 case SkClipStack::Element::kEmpty_Type:
1500 tmpClip.setEmpty(); 1502 tmpClip.setEmpty();
1501 break; 1503 break;
1502 default: { 1504 default: {
1503 SkPath path; 1505 SkPath path;
1504 element->asPath(&path); 1506 element->asPath(&path);
1505 rasterclip_path(&tmpClip, this, path, element->getOp(), element- >isAA()); 1507 rasterclip_path(&tmpClip, this, path, element->getOp(), element- >isAA());
1506 break; 1508 break;
1507 } 1509 }
1508 } 1510 }
1509 } 1511 }
1510 } 1512 }
1511 #endif 1513 #endif
1512 1514
1513 void SkCanvas::replayClips(ClipVisitor* visitor) const { 1515 void SkCanvas::replayClips(ClipVisitor* visitor) const {
1514 SkClipStack::B2TIter iter(fClipStack); 1516 SkClipStack::B2TIter iter(*fClipStack);
1515 const SkClipStack::Element* element; 1517 const SkClipStack::Element* element;
1516 1518
1517 while ((element = iter.next()) != NULL) { 1519 while ((element = iter.next()) != NULL) {
1518 element->replay(visitor); 1520 element->replay(visitor);
1519 } 1521 }
1520 } 1522 }
1521 1523
1522 /////////////////////////////////////////////////////////////////////////////// 1524 ///////////////////////////////////////////////////////////////////////////////
1523 1525
1524 bool SkCanvas::isClipEmpty() const { 1526 bool SkCanvas::isClipEmpty() const {
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after
2557 } 2559 }
2558 2560
2559 if (matrix) { 2561 if (matrix) {
2560 canvas->concat(*matrix); 2562 canvas->concat(*matrix);
2561 } 2563 }
2562 } 2564 }
2563 2565
2564 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2566 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2565 fCanvas->restoreToCount(fSaveCount); 2567 fCanvas->restoreToCount(fSaveCount);
2566 } 2568 }
OLDNEW
« no previous file with comments | « include/gpu/GrContext.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698