Make the clip reducer operate on int rects. Remove redundant Gr from func
name.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6890045
git-svn-id: http://skia.googlecode.com/svn/trunk@6688 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 8ee28dd..4745792 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -13,6 +13,13 @@
namespace GrReducedClip {
+// helper function
+void reduced_stack_walker(const SkClipStack& stack,
+ const SkRect& queryBounds,
+ ElementList* result,
+ InitialState* initialState,
+ bool* requiresAA);
+
/*
There are plenty of optimizations that could be added here. For example we could consider
checking for cases where an inverse path can be changed to a regular fill with a different op.
@@ -22,10 +29,12 @@
based on later intersect operations, and perhaps remove intersect-rects. We could optionally
take a rect in case the caller knows a bound on what is to be drawn through this clip.
*/
-void GrReduceClipStack(const SkClipStack& stack,
- const SkRect& queryBounds,
- ElementList* result,
- InitialState* initialState) {
+void ReduceClipStack(const SkClipStack& stack,
+ const SkIRect& queryBounds,
+ ElementList* result,
+ InitialState* initialState,
+ SkIRect* tighterBounds,
+ bool* requiresAA) {
result->reset();
if (stack.isWideOpen()) {
@@ -33,39 +42,98 @@
return;
}
+
+ // We initially look at whether the bounds alone is sufficient. We also use the stack bounds to
+ // attempt to compute the tighterBounds.
+
SkClipStack::BoundsType stackBoundsType;
SkRect stackBounds;
bool iior;
stack.getBounds(&stackBounds, &stackBoundsType, &iior);
+ const SkIRect* bounds = &queryBounds;
+
+ SkRect scalarQueryBounds = SkRect::MakeFromIRect(queryBounds);
+
if (iior) {
SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType);
SkRect isectRect;
- if (stackBounds.contains(queryBounds)) {
+ if (stackBounds.contains(scalarQueryBounds)) {
*initialState = kAllIn_InitialState;
- } else if (isectRect.intersect(stackBounds, queryBounds)) {
- // iior should only be true if aa/non-aa status matches among all elements.
- SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
- bool doAA = iter.prev()->isAA();
- SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
+ if (NULL != tighterBounds) {
+ *tighterBounds = queryBounds;
+ }
+ if (NULL != requiresAA) {
+ *requiresAA = false;
+ }
+ } else if (isectRect.intersect(stackBounds, scalarQueryBounds)) {
+ if (NULL != tighterBounds) {
+ isectRect.roundOut(tighterBounds);
+ SkRect scalarTighterBounds = SkRect::MakeFromIRect(*tighterBounds);
+ if (scalarTighterBounds == isectRect) {
+ // the round-out didn't add any area outside the clip rect.
+ *requiresAA = false;
+ *initialState = kAllIn_InitialState;
+ return;
+ }
+ *initialState = kAllOut_InitialState;
+ // iior should only be true if aa/non-aa status matches among all elements.
+ SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
+ bool doAA = iter.prev()->isAA();
+ SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
+ if (NULL != requiresAA) {
+ *requiresAA = doAA;
+ }
+ }
} else {
*initialState = kAllOut_InitialState;
+ if (NULL != requiresAA) {
+ *requiresAA = false;
+ }
}
return;
} else {
if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
- if (!SkRect::Intersects(stackBounds, queryBounds)) {
+ if (!SkRect::Intersects(stackBounds, scalarQueryBounds)) {
*initialState = kAllOut_InitialState;
+ if (NULL != requiresAA) {
+ *requiresAA = false;
+ }
return;
}
+ if (NULL != tighterBounds) {
+ SkIRect stackIBounds;
+ stackBounds.roundOut(&stackIBounds);
+ tighterBounds->intersect(queryBounds, stackIBounds);
+ bounds = tighterBounds;
+ }
} else {
- if (stackBounds.contains(queryBounds)) {
+ if (stackBounds.contains(scalarQueryBounds)) {
*initialState = kAllOut_InitialState;
+ if (NULL != requiresAA) {
+ *requiresAA = false;
+ }
return;
}
+ if (NULL != tighterBounds) {
+ *tighterBounds = queryBounds;
+ }
}
}
+ SkRect scalarBounds = SkRect::MakeFromIRect(*bounds);
+
+ // Now that we have determined the bounds to use and filtered out the trivial cases, call the
+ // helper that actually walks the stack.
+ reduced_stack_walker(stack, scalarBounds, result, initialState, requiresAA);
+}
+
+void reduced_stack_walker(const SkClipStack& stack,
+ const SkRect& queryBounds,
+ ElementList* result,
+ InitialState* initialState,
+ bool* requiresAA) {
+
// walk backwards until we get to:
// a) the beginning
// b) an operation that is known to make the bounds all inside/outside
@@ -80,6 +148,7 @@
bool emsmallens = false;
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
+ int numAAElements = 0;
while ((kUnknown_InitialState == *initialState)) {
const Element* element = iter.prev();
if (NULL == element) {
@@ -254,6 +323,9 @@
(queryBounds, SkRegion::kReverseDifference_Op, false));
} else {
result->addToHead(*element);
+ if (element->isAA()) {
+ ++numAAElements;
+ }
}
}
}
@@ -262,7 +334,6 @@
(kAllIn_InitialState == *initialState && !emsmallens)) {
result->reset();
} else {
- int clipsToSkip = 0;
Element* element = result->headIter().get();
while (NULL != element) {
bool skippable = false;
@@ -308,7 +379,6 @@
}
break;
case SkRegion::kReplace_Op:
- SkASSERT(!clipsToSkip); // replace should always be the first op
skippable = false; // we would have skipped it in the backwards walk if we
// could've.
break;
@@ -319,10 +389,16 @@
if (!skippable) {
break;
} else {
+ if (element->isAA()) {
+ --numAAElements;
+ }
result->popHead();
element = result->headIter().get();
}
}
}
+ if (NULL != requiresAA) {
+ *requiresAA = numAAElements > 0;
+ }
}
} // namespace GrReducedClip