зеркало из https://github.com/mozilla/moz-skia.git
Make the clip stack reduction test generate inverse filled paths.
Also adds some comments to GrReduceClipStack. R=robertphillips@google.com Review URL: https://codereview.appspot.com/6847109 git-svn-id: http://skia.googlecode.com/svn/trunk@6561 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
d198a5b8a7
Коммит
705e840944
|
@ -111,6 +111,13 @@ public:
|
||||||
*/
|
*/
|
||||||
bool nextBool() { return this->nextU() >= 0x80000000; }
|
bool nextBool() { return this->nextU() >= 0x80000000; }
|
||||||
|
|
||||||
|
/** A biased version of nextBool().
|
||||||
|
*/
|
||||||
|
bool nextBiasedBool(SkScalar fractionTrue) {
|
||||||
|
SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
|
||||||
|
return this->nextUScalar1() <= fractionTrue;
|
||||||
|
}
|
||||||
|
|
||||||
/** Return the next pseudo random number as a signed 64bit value.
|
/** Return the next pseudo random number as a signed 64bit value.
|
||||||
*/
|
*/
|
||||||
void next64(Sk64* a) {
|
void next64(Sk64* a) {
|
||||||
|
|
|
@ -130,7 +130,7 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
case SkRegion::kIntersect_Op:
|
case SkRegion::kIntersect_Op:
|
||||||
if (*resultsAreBounded) {
|
if (*resultsAreBounded) {
|
||||||
// check if the shape intersected contains the entire bounds and therefore can
|
// check if the shape intersected contains the entire bounds and therefore can
|
||||||
// be skipped or it is outside the entire bounds and therfore makes the clip
|
// be skipped or it is outside the entire bounds and therefore makes the clip
|
||||||
// empty.
|
// empty.
|
||||||
if (clip->isInverseFilled()) {
|
if (clip->isInverseFilled()) {
|
||||||
if (clip->contains(*resultBounds)) {
|
if (clip->contains(*resultBounds)) {
|
||||||
|
@ -154,8 +154,8 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
break;
|
break;
|
||||||
case SkRegion::kUnion_Op:
|
case SkRegion::kUnion_Op:
|
||||||
if (*resultsAreBounded) {
|
if (*resultsAreBounded) {
|
||||||
// If the unioned shape contains the entire bounds then after this element
|
// If the union-ed shape contains the entire bounds then after this element
|
||||||
// the bounds is entirely inside the clip. If the unioned shape is outside the
|
// the bounds is entirely inside the clip. If the union-ed shape is outside the
|
||||||
// bounds then this op can be skipped.
|
// bounds then this op can be skipped.
|
||||||
if (clip->isInverseFilled()) {
|
if (clip->isInverseFilled()) {
|
||||||
if (clip->contains(*resultBounds)) {
|
if (clip->contains(*resultBounds)) {
|
||||||
|
@ -179,6 +179,10 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
break;
|
break;
|
||||||
case SkRegion::kXOR_Op:
|
case SkRegion::kXOR_Op:
|
||||||
if (*resultsAreBounded) {
|
if (*resultsAreBounded) {
|
||||||
|
// If the bounds is entirely inside the shape being xor-ed then the effect is
|
||||||
|
// to flip the inside/outside state of every point in the bounds. We may be
|
||||||
|
// able to take advantage of this in the forward pass. If the xor-ed shape
|
||||||
|
// doesn't intersect the bounds then it can be skipped.
|
||||||
if (clip->isInverseFilled()) {
|
if (clip->isInverseFilled()) {
|
||||||
if (clip->contains(*resultBounds)) {
|
if (clip->contains(*resultBounds)) {
|
||||||
skippable = true;
|
skippable = true;
|
||||||
|
@ -198,6 +202,10 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SkRegion::kReverseDifference_Op:
|
case SkRegion::kReverseDifference_Op:
|
||||||
|
// When the bounds is entirely within the rev-diff shape then this behaves like xor
|
||||||
|
// and reverses every point inside the bounds. If the shape is completely outside
|
||||||
|
// the bounds then we know after this element is applied that the bounds will be
|
||||||
|
// all outside the current clip.B
|
||||||
if (*resultsAreBounded) {
|
if (*resultsAreBounded) {
|
||||||
if (clip->isInverseFilled()) {
|
if (clip->isInverseFilled()) {
|
||||||
if (clip->contains(*resultBounds)) {
|
if (clip->contains(*resultBounds)) {
|
||||||
|
@ -220,7 +228,11 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SkRegion::kReplace_Op:
|
case SkRegion::kReplace_Op:
|
||||||
if (*resultsAreBounded) {
|
// Replace will always terminate our walk. We will either begin the forward walk
|
||||||
|
// at the replace op or detect here than the shape is either completely inside
|
||||||
|
// or completely outside the bounds. In this latter case it can be skipped by
|
||||||
|
// setting the correct value for initialState.
|
||||||
|
if (*resultsAreBounded) {
|
||||||
if (clip->isInverseFilled()) {
|
if (clip->isInverseFilled()) {
|
||||||
if (clip->contains(*resultBounds)) {
|
if (clip->contains(*resultBounds)) {
|
||||||
*initialState = kAllOut_InitialState;
|
*initialState = kAllOut_InitialState;
|
||||||
|
@ -276,9 +288,11 @@ void GrReduceClipStack(const SkClipStack& stack,
|
||||||
bool skippable = false;
|
bool skippable = false;
|
||||||
switch (clip->fOp) {
|
switch (clip->fOp) {
|
||||||
case SkRegion::kDifference_Op:
|
case SkRegion::kDifference_Op:
|
||||||
|
// subtracting from the empty set yields the empty set.
|
||||||
skippable = kAllOut_InitialState == *initialState;
|
skippable = kAllOut_InitialState == *initialState;
|
||||||
break;
|
break;
|
||||||
case SkRegion::kIntersect_Op:
|
case SkRegion::kIntersect_Op:
|
||||||
|
// intersecting with the empty set yields the empty set
|
||||||
skippable = kAllOut_InitialState == *initialState;
|
skippable = kAllOut_InitialState == *initialState;
|
||||||
break;
|
break;
|
||||||
case SkRegion::kUnion_Op:
|
case SkRegion::kUnion_Op:
|
||||||
|
|
|
@ -647,25 +647,44 @@ static void test_iter_rect_merging(skiatest::Reporter* reporter) {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
|
// Functions that add a shape to the clip stack. The shape is computed from a rectangle.
|
||||||
|
// AA is always disabled since the clip stack reducer can cause changes in aa rasterization of the
|
||||||
|
// stack. A fractional edge repeated in different elements may be rasterized fewer times using the
|
||||||
|
// reduced stack.
|
||||||
|
typedef void (*AddElementFunc) (const SkRect& rect,
|
||||||
|
bool invert,
|
||||||
|
SkRegion::Op op,
|
||||||
|
SkClipStack* stack);
|
||||||
|
|
||||||
typedef void (*AddElementFunc) (const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack);
|
static void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
|
||||||
|
|
||||||
static void add_round_rect(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
|
|
||||||
SkPath path;
|
SkPath path;
|
||||||
SkScalar rx = rect.width() / 10;
|
SkScalar rx = rect.width() / 10;
|
||||||
SkScalar ry = rect.width() / 20;
|
SkScalar ry = rect.height() / 20;
|
||||||
path.addRoundRect(rect, rx, ry);
|
path.addRoundRect(rect, rx, ry);
|
||||||
stack->clipDevPath(path, op, aa);
|
if (invert) {
|
||||||
|
path.setFillType(SkPath::kInverseWinding_FillType);
|
||||||
|
}
|
||||||
|
stack->clipDevPath(path, op, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void add_rect(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
|
static void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
|
||||||
stack->clipDevRect(rect, op, aa);
|
if (invert) {
|
||||||
|
SkPath path;
|
||||||
|
path.addRect(rect);
|
||||||
|
path.setFillType(SkPath::kInverseWinding_FillType);
|
||||||
|
stack->clipDevPath(path, op, false);
|
||||||
|
} else {
|
||||||
|
stack->clipDevRect(rect, op, false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void add_oval(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
|
static void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
|
||||||
SkPath path;
|
SkPath path;
|
||||||
path.addOval(rect);
|
path.addOval(rect);
|
||||||
stack->clipDevPath(path, op, aa);
|
if (invert) {
|
||||||
|
path.setFillType(SkPath::kInverseWinding_FillType);
|
||||||
|
}
|
||||||
|
stack->clipDevPath(path, op, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void add_elem_to_stack(const SkClipStack::Iter::Clip& clip, SkClipStack* stack) {
|
static void add_elem_to_stack(const SkClipStack::Iter::Clip& clip, SkClipStack* stack) {
|
||||||
|
@ -706,11 +725,12 @@ static void print_clip(const SkClipStack::Iter::Clip& clip) {
|
||||||
"RD",
|
"RD",
|
||||||
"RP",
|
"RP",
|
||||||
};
|
};
|
||||||
if (clip.fRect || clip.fPath) {
|
if (NULL != clip.fRect || NULL != clip.fPath) {
|
||||||
const SkRect& bounds = clip.getBounds();
|
const SkRect& bounds = clip.getBounds();
|
||||||
SkDebugf("%s %s [%f %f] x [%f %f]\n",
|
SkDebugf("%s %s %s [%f %f] x [%f %f]\n",
|
||||||
kOpStrs[clip.fOp],
|
kOpStrs[clip.fOp],
|
||||||
(clip.fRect ? "R" : "P"),
|
(NULL != clip.fRect ? "R" : "P"),
|
||||||
|
((NULL != clip.fPath && clip.fPath->isInverseFillType() ? "I" : " ")),
|
||||||
bounds.fLeft, bounds.fRight, bounds.fTop, bounds.fBottom);
|
bounds.fLeft, bounds.fRight, bounds.fTop, bounds.fBottom);
|
||||||
} else {
|
} else {
|
||||||
SkDebugf("EM\n");
|
SkDebugf("EM\n");
|
||||||
|
@ -748,6 +768,9 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
|
||||||
// the optimizer.
|
// the optimizer.
|
||||||
static const int kReplaceDiv = 4 * kMaxElemsPerTest;
|
static const int kReplaceDiv = 4 * kMaxElemsPerTest;
|
||||||
|
|
||||||
|
// We want to test inverse fills. However, they are quite rare in practice so don't over do it.
|
||||||
|
static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
|
||||||
|
|
||||||
static const AddElementFunc kElementFuncs[] = {
|
static const AddElementFunc kElementFuncs[] = {
|
||||||
add_rect,
|
add_rect,
|
||||||
add_round_rect,
|
add_round_rect,
|
||||||
|
@ -781,10 +804,8 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
|
||||||
|
|
||||||
SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
|
SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
|
||||||
|
|
||||||
// AA is always disabled. The optimizer can cause changes in aa rasterization of the
|
bool invert = r.nextBiasedBool(kFractionInverted);
|
||||||
// clip stack. A fractional edge repeated in different elements may be rasterized fewer
|
kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, invert, op, &stack);
|
||||||
// times using the reduced stack.
|
|
||||||
kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, false, op, &stack);
|
|
||||||
if (doSave) {
|
if (doSave) {
|
||||||
stack.save();
|
stack.save();
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче