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
This commit is contained in:
bsalomon@google.com 2012-12-06 14:23:20 +00:00
Родитель 0264fb4543
Коммит 34cd70a581
3 изменённых файлов: 115 добавлений и 21 удалений

Просмотреть файл

@ -13,6 +13,13 @@ typedef SkClipStack::Element Element;
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 @@ for the case where the bounds are kInsideOut_BoundsType. We could restrict earli
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 @@ void GrReduceClipStack(const SkClipStack& stack,
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 @@ void GrReduceClipStack(const SkClipStack& stack,
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 @@ void GrReduceClipStack(const SkClipStack& stack,
(queryBounds, SkRegion::kReverseDifference_Op, false));
} else {
result->addToHead(*element);
if (element->isAA()) {
++numAAElements;
}
}
}
}
@ -262,7 +334,6 @@ void GrReduceClipStack(const SkClipStack& stack,
(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 @@ void GrReduceClipStack(const SkClipStack& stack,
}
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 @@ void GrReduceClipStack(const SkClipStack& stack,
if (!skippable) {
break;
} else {
if (element->isAA()) {
--numAAElements;
}
result->popHead();
element = result->headIter().get();
}
}
}
if (NULL != requiresAA) {
*requiresAA = numAAElements > 0;
}
}
} // namespace GrReducedClip

Просмотреть файл

@ -22,12 +22,19 @@ enum InitialState {
* This function takes a clip stack and a query rectangle and it produces a reduced set of
* SkClipStack::Elements that are equivalent to applying the full stack to the rectangle. The
* initial state of the query rectangle before the first clip element is applied is returned via
* initialState. This function is declared here so that it can be unit-tested. It may become a
* member function of SkClipStack when its interface is determined to be stable.
* initialState. Optionally, the caller can request a tighter bounds on the clip be returned via
* tighterBounds. If not NULL, tighterBounds will always be contained by queryBounds after return.
* If tighterBounds is specified then it is assumed that the caller will implicitly clip against it.
* If the caller specifies non-NULL for requiresAA then it will indicate whether anti-aliasing is
* required to process any of the elements in the result.
*
* This may become a member function of SkClipStack when its interface is determined to be stable.
*/
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 = NULL,
bool* requiresAA = NULL);
} // namespace GrReducedClip

Просмотреть файл

@ -669,7 +669,13 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
ElementList reducedClips;
GrReducedClip::InitialState initial;
GrReducedClip::GrReduceClipStack(stack, inflatedBounds, &reducedClips, &initial);
SkIRect tBounds;
SkIRect* tightBounds = r.nextBool() ? &tBounds : NULL;
GrReducedClip::ReduceClipStack(stack,
inflatedIBounds,
&reducedClips,
&initial,
tightBounds);
// Build a new clip stack based on the reduced clip elements
SkClipStack reducedStack;
@ -681,6 +687,11 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
add_elem_to_stack(*iter.get(), &reducedStack);
}
// GrReducedClipStack assumes that the final result is clipped to the returned bounds
if (NULL != tightBounds) {
reducedStack.clipDevRect(*tightBounds, SkRegion::kIntersect_Op);
}
// convert both the original stack and reduced stack to SkRegions and see if they're equal
SkRegion region;
SkRegion reducedRegion;