Fix inverse union complex clip stencil rules, skip screen filling rectangles
Review URL: http://codereview.appspot.com/5480054/
git-svn-id: http://skia.googlecode.com/svn/trunk@2848 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index eb96c57..a949acd 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -446,6 +446,7 @@
// whether the initial clear should be to the inside- or outside-the-clip value,
// and what op should be used to draw the first element that isn't skipped.
int process_initial_clip_elements(const GrClip& clip,
+ const GrRect& bounds,
bool* clearToInside,
GrSetOp* startOp) {
@@ -468,6 +469,12 @@
done = true;
break;
case kIntersect_SetOp:
+ // if this element contains the entire bounds then we
+ // can skip it.
+ if (kRect_ClipType == clip.getElementType(curr)
+ && clip.getRect(curr).contains(bounds)) {
+ break;
+ }
// if everything is initially clearToInside then intersect is
// same as clear to 0 and treat as a replace. Otherwise,
// set stays empty.
@@ -595,7 +602,9 @@
bool clearToInside;
GrSetOp startOp = kReplace_SetOp; // suppress warning
- int start = process_initial_clip_elements(clip, &clearToInside,
+ int start = process_initial_clip_elements(clip,
+ rtRect,
+ &clearToInside,
&startOp);
this->clearStencilClip(clipRect, clearToInside);
@@ -621,6 +630,12 @@
canRenderDirectToStencil = true;
fill = kEvenOdd_PathFill;
fillInverted = false;
+ // there is no point in intersecting a screen filling
+ // rectangle.
+ if (kIntersect_SetOp == clip.getOp(c) &&
+ clip.getRect(c).contains(rtRect)) {
+ continue;
+ }
} else {
fill = clip.getPathFill(c);
fillInverted = GrIsFillInverted(fill);
diff --git a/src/gpu/GrStencil.cpp b/src/gpu/GrStencil.cpp
index a66fbfd..81b3b8d 100644
--- a/src/gpu/GrStencil.cpp
+++ b/src/gpu/GrStencil.cpp
@@ -110,26 +110,25 @@
0xffff, 0xffff
};
-// for inverse first pass finds non-zerp user with clip bit set
-// and converts it to just clip bit set
+// first pass finds zeros in the user bits and if found sets
+// the clip bit to 1
static const GrStencilSettings gInvUserToClipUnionPass0 = {
kReplace_StencilOp, kReplace_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
- kLess_StencilFunc, kLess_StencilFunc,
- 0xffff, 0xffff,
- 0x0000, 0x0000, // set clip bit
- 0xffff, 0xffff
-};
-
-// second pass lets anything through with a nonzero user portion
-// and writes a ref value with just the clip bit set to it.
-static const GrStencilSettings gInvUserToClipUnionPass1 = {
- kReplace_StencilOp, kReplace_StencilOp,
- kZero_StencilOp, kZero_StencilOp,
- kLess_StencilFunc, kLess_StencilFunc,
+ kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000, // set clip bit
- 0xffff, 0xffff
+ 0x0000, 0x0000 // set clip bit
+};
+
+// second pass zeros the user bits
+static const GrStencilSettings gInvUserToClipUnionPass1 = {
+ kZero_StencilOp, kZero_StencilOp,
+ kZero_StencilOp, kZero_StencilOp,
+ kLess_StencilFunc, kLess_StencilFunc,
+ 0xffff, 0xffff,
+ 0x0000, 0x0000,
+ 0xffff, 0xffff // unset clip bit
};
///////
@@ -301,14 +300,16 @@
*numPasses = 2;
if (invertedFill) {
settings[0] = gInvUserToClipUnionPass0;
+ settings[0].fFrontFuncMask &= ~stencilClipMask;
+ settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
settings[0].fFrontFuncRef |= stencilClipMask;
- settings[0].fBackFuncRef = settings[0].fFrontFuncMask;
+ settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
+ settings[0].fFrontWriteMask |= stencilClipMask;
+ settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
settings[1] = gInvUserToClipUnionPass1;
- settings[1].fFrontFuncMask &= ~stencilClipMask;
- settings[1].fFrontFuncRef |= stencilClipMask;
- settings[1].fBackFuncMask = settings[1].fFrontFuncMask;
- settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
+ settings[1].fFrontWriteMask &= ~stencilClipMask;
+ settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
} else {
settings[0] = gUserToClipUnionPass0;