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
This commit is contained in:
bsalomon@google.com 2011-03-24 16:55:45 +00:00
parent f6a7c1106e
commit 7f5875d334
4 changed files with 44 additions and 22 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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: