From 6b20c2ded4bc546853719c88d1cf13b36fd89bcb Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Fri, 9 Dec 2011 21:23:46 +0000 Subject: [PATCH] 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 --- src/gpu/GrGpu.cpp | 17 ++++++++++++++++- src/gpu/GrStencil.cpp | 33 +++++++++++++++++---------------- 2 files changed, 33 insertions(+), 17 deletions(-) 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 @@ namespace { // 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 @@ int process_initial_clip_elements(const GrClip& clip, 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 GrGpu::setupClipAndFlushState(GrPrimitiveType type) { 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 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { 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 @@ static const GrStencilSettings gUserToClipUnionPass1 = { 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, + kEqual_StencilFunc, kEqual_StencilFunc, + 0xffff, 0xffff, // unset clip bit 0x0000, 0x0000, // set clip bit - 0xffff, 0xffff + 0x0000, 0x0000 // set clip bit }; -// second pass lets anything through with a nonzero user portion -// and writes a ref value with just the clip bit set to it. +// second pass zeros the user bits static const GrStencilSettings gInvUserToClipUnionPass1 = { - kReplace_StencilOp, kReplace_StencilOp, + kZero_StencilOp, kZero_StencilOp, kZero_StencilOp, kZero_StencilOp, kLess_StencilFunc, kLess_StencilFunc, - 0xffff, 0xffff, // unset clip bit - 0x0000, 0x0000, // set clip bit - 0xffff, 0xffff + 0xffff, 0xffff, + 0x0000, 0x0000, + 0xffff, 0xffff // unset clip bit }; /////// @@ -301,14 +300,16 @@ bool GrStencilSettings::GetClipPasses(GrSetOp op, *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; -- 2.7.4