From 7f5875d33462f0f1b96a36ac530fb1f2edb1d535 Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Thu, 24 Mar 2011 16:55:45 +0000 Subject: [PATCH] Fix direct-to-stencil clippath rendering logic in GrGpu. Review URL: http://codereview.appspot.com/4273104/ git-svn-id: http://skia.googlecode.com/svn/trunk@1001 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gpu/src/GrGpu.cpp | 59 ++++++++++++++++++++++++++------------ gpu/src/GrPathRenderer.cpp | 2 +- gpu/src/GrPathRenderer.h | 3 +- gpu/src/GrStencil.cpp | 2 +- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index 2d763e299a..d60287b189 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -414,43 +414,63 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { // enabled at bottom of loop this->disableState(kModifyStencilClip_StateBit); - bool canDrawDirectToClip; + bool canRenderDirectToStencil; // can the clip element be drawn + // directly to the stencil buffer + // with a non-inverted fill rule + // without extra passes to + // resolve in/out status. if (kRect_ClipType == clip.getElementType(c)) { - canDrawDirectToClip = true; + canRenderDirectToStencil = true; fill = kEvenOdd_PathFill; } else { fill = clip.getPathFill(c); GrPathRenderer* pr = this->getPathRenderer(); - canDrawDirectToClip = pr->requiresStencilPass(this, clip.getPath(c), fill); + canRenderDirectToStencil = + !pr->requiresStencilPass(this, clip.getPath(c), + NonInvertedFill(fill)); } GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c); int passes; GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; - canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip, - clipBit, IsFillInverted(fill), - &passes, stencilSettings); + bool canDrawDirectToClip; // Given the renderer, the element, + // fill rule, and set operation can + // we render the element directly to + // stencil bit used for clipping. + canDrawDirectToClip = + GrStencilSettings::GetClipPasses(op, + canRenderDirectToStencil, + clipBit, + IsFillInverted(fill), + &passes, stencilSettings); // draw the element to the client stencil bits if necessary if (!canDrawDirectToClip) { + static const GrStencilSettings gDrawToStencil = { + kIncClamp_StencilOp, kIncClamp_StencilOp, + kIncClamp_StencilOp, kIncClamp_StencilOp, + kAlways_StencilFunc, kAlways_StencilFunc, + 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, + }; + SET_RANDOM_COLOR if (kRect_ClipType == clip.getElementType(c)) { - static const GrStencilSettings gDrawToStencil = { - kIncClamp_StencilOp, kIncClamp_StencilOp, - kIncClamp_StencilOp, kIncClamp_StencilOp, - kAlways_StencilFunc, kAlways_StencilFunc, - 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, - }; this->setStencil(gDrawToStencil); - SET_RANDOM_COLOR this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { - SET_RANDOM_COLOR - getPathRenderer()->drawPathToStencil(this, clip.getPath(c), - NonInvertedFill(fill), - NULL); + if (canRenderDirectToStencil) { + this->setStencil(gDrawToStencil); + getPathRenderer()->drawPath(this, 0, + clip.getPath(c), + NonInvertedFill(fill), + NULL); + } else { + getPathRenderer()->drawPathToStencil(this, clip.getPath(c), + NonInvertedFill(fill), + NULL); + } } } @@ -465,6 +485,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { SET_RANDOM_COLOR + GrAssert(!IsFillInverted(fill)); getPathRenderer()->drawPath(this, 0, clip.getPath(c), fill, NULL); diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp index 6d7aabb1e0..fc3c124ee0 100644 --- a/gpu/src/GrPathRenderer.cpp +++ b/gpu/src/GrPathRenderer.cpp @@ -294,7 +294,7 @@ static inline bool single_pass_path(const GrDrawTarget& target, bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target, GrPathIter* path, GrPathFill fill) const { - return single_pass_path(*target, *path, fill); + return !single_pass_path(*target, *path, fill); } void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target, diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h index 19e284f3fa..30bdb5aaed 100644 --- a/gpu/src/GrPathRenderer.h +++ b/gpu/src/GrPathRenderer.h @@ -68,7 +68,8 @@ public: * * @param target target that the path will be rendered to * @param path the path that will be drawn - * @param fill the fill rule that will be used + * @param fill the fill rule that will be used, will never be an inverse + * rule. * * @return false if this path renderer can generate interior-only fragments * without changing the stencil settings on the target. If it diff --git a/gpu/src/GrStencil.cpp b/gpu/src/GrStencil.cpp index a1c8c09b2d..c366f619ad 100644 --- a/gpu/src/GrStencil.cpp +++ b/gpu/src/GrStencil.cpp @@ -249,7 +249,7 @@ bool GrStencilSettings::GetClipPasses(GrSetOp op, bool invertedFill, int* numPasses, GrStencilSettings settings[kMaxStencilClipPasses]) { - if (canBeDirect) { + if (canBeDirect && !invertedFill) { *numPasses = 0; switch (op) { case kReplace_SetOp: