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

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

Issue 48593003: Avoid re-rendering stencil clip for every draw with reducable clip stack (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: gcc-4.2 mac os 10.6 fix Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « include/core/SkClipStack.h ('k') | src/gpu/GrClipMaskCache.h » ('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 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
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 #include "SkClipStack.h" 8 #include "SkClipStack.h"
9 #include "SkPath.h" 9 #include "SkPath.h"
10 #include "SkThread.h" 10 #include "SkThread.h"
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 fSaveCount -= 1; 445 fSaveCount -= 1;
446 restoreTo(fSaveCount); 446 restoreTo(fSaveCount);
447 } 447 }
448 448
449 void SkClipStack::restoreTo(int saveCount) { 449 void SkClipStack::restoreTo(int saveCount) {
450 while (!fDeque.empty()) { 450 while (!fDeque.empty()) {
451 Element* element = (Element*)fDeque.back(); 451 Element* element = (Element*)fDeque.back();
452 if (element->fSaveCount <= saveCount) { 452 if (element->fSaveCount <= saveCount) {
453 break; 453 break;
454 } 454 }
455 this->purgeClip(element);
456 element->~Element(); 455 element->~Element();
457 fDeque.pop_back(); 456 fDeque.pop_back();
458 } 457 }
459 } 458 }
460 459
461 void SkClipStack::getBounds(SkRect* canvFiniteBound, 460 void SkClipStack::getBounds(SkRect* canvFiniteBound,
462 BoundsType* boundType, 461 BoundsType* boundType,
463 bool* isIntersectionOfRects) const { 462 bool* isIntersectionOfRects) const {
464 SkASSERT(NULL != canvFiniteBound && NULL != boundType); 463 SkASSERT(NULL != canvFiniteBound && NULL != boundType);
465 464
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 Element* element = (Element*) iter.prev(); 532 Element* element = (Element*) iter.prev();
534 533
535 if (NULL != element) { 534 if (NULL != element) {
536 if (element->canBeIntersectedInPlace(fSaveCount, op)) { 535 if (element->canBeIntersectedInPlace(fSaveCount, op)) {
537 switch (element->fType) { 536 switch (element->fType) {
538 case Element::kEmpty_Type: 537 case Element::kEmpty_Type:
539 element->checkEmpty(); 538 element->checkEmpty();
540 return; 539 return;
541 case Element::kRect_Type: 540 case Element::kRect_Type:
542 if (element->rectRectIntersectAllowed(rect, doAA)) { 541 if (element->rectRectIntersectAllowed(rect, doAA)) {
543 this->purgeClip(element);
544 if (!element->fRect.intersect(rect)) { 542 if (!element->fRect.intersect(rect)) {
545 element->setEmpty(); 543 element->setEmpty();
546 return; 544 return;
547 } 545 }
548 546
549 element->fDoAA = doAA; 547 element->fDoAA = doAA;
550 Element* prev = (Element*) iter.prev(); 548 Element* prev = (Element*) iter.prev();
551 element->updateBoundAndGenID(prev); 549 element->updateBoundAndGenID(prev);
552 return; 550 return;
553 } 551 }
554 break; 552 break;
555 case Element::kPath_Type: 553 case Element::kPath_Type:
556 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { 554 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) {
557 this->purgeClip(element);
558 element->setEmpty(); 555 element->setEmpty();
559 return; 556 return;
560 } 557 }
561 break; 558 break;
562 } 559 }
563 } else if (SkRegion::kReplace_Op == op) { 560 } else if (SkRegion::kReplace_Op == op) {
564 this->restoreTo(fSaveCount - 1); 561 this->restoreTo(fSaveCount - 1);
565 element = (Element*) fDeque.back(); 562 element = (Element*) fDeque.back();
566 } 563 }
567 } 564 }
568 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); 565 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA);
569 ((Element*) fDeque.back())->updateBoundAndGenID(element); 566 ((Element*) fDeque.back())->updateBoundAndGenID(element);
570
571 if (element && element->fSaveCount == fSaveCount) {
572 this->purgeClip(element);
573 }
574 } 567 }
575 568
576 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { 569 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
577 SkRect alt; 570 SkRect alt;
578 if (path.isRect(&alt) && !path.isInverseFillType()) { 571 if (path.isRect(&alt) && !path.isInverseFillType()) {
579 return this->clipDevRect(alt, op, doAA); 572 return this->clipDevRect(alt, op, doAA);
580 } 573 }
581 574
582 Element* element = (Element*)fDeque.back(); 575 Element* element = (Element*)fDeque.back();
583 if (NULL != element) { 576 if (NULL != element) {
584 if (element->canBeIntersectedInPlace(fSaveCount, op)) { 577 if (element->canBeIntersectedInPlace(fSaveCount, op)) {
585 const SkRect& pathBounds = path.getBounds(); 578 const SkRect& pathBounds = path.getBounds();
586 switch (element->fType) { 579 switch (element->fType) {
587 case Element::kEmpty_Type: 580 case Element::kEmpty_Type:
588 element->checkEmpty(); 581 element->checkEmpty();
589 return; 582 return;
590 case Element::kRect_Type: 583 case Element::kRect_Type:
591 if (!SkRect::Intersects(element->fRect, pathBounds)) { 584 if (!SkRect::Intersects(element->fRect, pathBounds)) {
592 this->purgeClip(element);
593 element->setEmpty(); 585 element->setEmpty();
594 return; 586 return;
595 } 587 }
596 break; 588 break;
597 case Element::kPath_Type: 589 case Element::kPath_Type:
598 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun ds)) { 590 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun ds)) {
599 this->purgeClip(element);
600 element->setEmpty(); 591 element->setEmpty();
601 return; 592 return;
602 } 593 }
603 break; 594 break;
604 } 595 }
605 } else if (SkRegion::kReplace_Op == op) { 596 } else if (SkRegion::kReplace_Op == op) {
606 this->restoreTo(fSaveCount - 1); 597 this->restoreTo(fSaveCount - 1);
607 element = (Element*) fDeque.back(); 598 element = (Element*) fDeque.back();
608 } 599 }
609 } 600 }
610 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); 601 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA);
611 ((Element*) fDeque.back())->updateBoundAndGenID(element); 602 ((Element*) fDeque.back())->updateBoundAndGenID(element);
612
613 if (element && element->fSaveCount == fSaveCount) {
614 this->purgeClip(element);
615 }
616 } 603 }
617 604
618 void SkClipStack::clipEmpty() { 605 void SkClipStack::clipEmpty() {
619 606
620 Element* element = (Element*) fDeque.back(); 607 Element* element = (Element*) fDeque.back();
621 608
622 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter sect_Op)) { 609 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter sect_Op)) {
623 switch (element->fType) { 610 switch (element->fType) {
624 case Element::kEmpty_Type: 611 case Element::kEmpty_Type:
625 element->checkEmpty(); 612 element->checkEmpty();
626 return; 613 return;
627 case Element::kRect_Type: 614 case Element::kRect_Type:
628 case Element::kPath_Type: 615 case Element::kPath_Type:
629 this->purgeClip(element);
630 element->setEmpty(); 616 element->setEmpty();
631 return; 617 return;
632 } 618 }
633 } 619 }
634 new (fDeque.push_back()) Element(fSaveCount); 620 new (fDeque.push_back()) Element(fSaveCount);
635 621
636 if (element && element->fSaveCount == fSaveCount) {
637 this->purgeClip(element);
638 }
639 ((Element*)fDeque.back())->fGenID = kEmptyGenID; 622 ((Element*)fDeque.back())->fGenID = kEmptyGenID;
640 } 623 }
641 624
642 bool SkClipStack::isWideOpen() const { 625 bool SkClipStack::isWideOpen() const {
643 if (0 == fDeque.count()) { 626 return this->getTopmostGenID() == kWideOpenGenID;
644 return true;
645 }
646
647 const Element* back = (const Element*) fDeque.back();
648 return kWideOpenGenID == back->fGenID ||
649 (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBoun d.isEmpty());
650 } 627 }
651 628
652 /////////////////////////////////////////////////////////////////////////////// 629 ///////////////////////////////////////////////////////////////////////////////
653 630
654 SkClipStack::Iter::Iter() : fStack(NULL) { 631 SkClipStack::Iter::Iter() : fStack(NULL) {
655 } 632 }
656 633
657 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) 634 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
658 : fStack(&stack) { 635 : fStack(&stack) {
659 this->reset(stack, startLoc); 636 this->reset(stack, startLoc);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 } 710 }
734 711
735 // but is converted to device space here 712 // but is converted to device space here
736 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY)); 713 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY));
737 714
738 if (!devBounds->intersect(temp)) { 715 if (!devBounds->intersect(temp)) {
739 devBounds->setEmpty(); 716 devBounds->setEmpty();
740 } 717 }
741 } 718 }
742 719
743 void SkClipStack::addPurgeClipCallback(PFPurgeClipCB callback, void* data) const {
744 ClipCallbackData temp = { callback, data };
745 fCallbackData.append(1, &temp);
746 }
747
748 void SkClipStack::removePurgeClipCallback(PFPurgeClipCB callback, void* data) co nst {
749 ClipCallbackData temp = { callback, data };
750 int index = fCallbackData.find(temp);
751 if (index >= 0) {
752 fCallbackData.removeShuffle(index);
753 }
754 }
755
756 // The clip state represented by 'element' will never be used again. Purge it.
757 void SkClipStack::purgeClip(Element* element) {
758 SkASSERT(NULL != element);
759 if (element->fGenID >= 0 && element->fGenID < kFirstUnreservedGenID) {
760 return;
761 }
762
763 for (int i = 0; i < fCallbackData.count(); ++i) {
764 (*fCallbackData[i].fCallback)(element->fGenID, fCallbackData[i].fData);
765 }
766
767 // Invalidate element's gen ID so handlers can detect already handled record s
768 element->fGenID = kInvalidGenID;
769 }
770
771 int32_t SkClipStack::GetNextGenID() { 720 int32_t SkClipStack::GetNextGenID() {
772 // TODO: handle overflow. 721 // TODO: handle overflow.
773 return sk_atomic_inc(&gGenID); 722 return sk_atomic_inc(&gGenID);
774 } 723 }
775 724
776 int32_t SkClipStack::getTopmostGenID() const { 725 int32_t SkClipStack::getTopmostGenID() const {
777
778 if (fDeque.empty()) { 726 if (fDeque.empty()) {
779 return kInvalidGenID; 727 return kWideOpenGenID;
780 } 728 }
781 729
782 Element* element = (Element*)fDeque.back(); 730 const Element* back = static_cast<const Element*>(fDeque.back());
783 return element->fGenID; 731 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is Empty()) {
732 return kWideOpenGenID;
733 }
734
735 return back->getGenID();
784 } 736 }
OLDNEW
« no previous file with comments | « include/core/SkClipStack.h ('k') | src/gpu/GrClipMaskCache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698