michael@0: michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "GrStencilAndCoverPathRenderer.h" michael@0: #include "GrContext.h" michael@0: #include "GrDrawTargetCaps.h" michael@0: #include "GrGpu.h" michael@0: #include "GrPath.h" michael@0: #include "SkStrokeRec.h" michael@0: michael@0: GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) { michael@0: SkASSERT(NULL != context); michael@0: SkASSERT(NULL != context->getGpu()); michael@0: if (context->getGpu()->caps()->pathRenderingSupport()) { michael@0: return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu())); michael@0: } else { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { michael@0: SkASSERT(gpu->caps()->pathRenderingSupport()); michael@0: fGpu = gpu; michael@0: gpu->ref(); michael@0: } michael@0: michael@0: GrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { michael@0: fGpu->unref(); michael@0: } michael@0: michael@0: bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, michael@0: const SkStrokeRec& stroke, michael@0: const GrDrawTarget* target, michael@0: bool antiAlias) const { michael@0: return !stroke.isHairlineStyle() && michael@0: !antiAlias && // doesn't do per-path AA, relies on the target having MSAA michael@0: NULL != target->getDrawState().getRenderTarget()->getStencilBuffer() && michael@0: target->getDrawState().getStencil().isDisabled(); michael@0: } michael@0: michael@0: GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( michael@0: const SkPath&, michael@0: const SkStrokeRec& , michael@0: const GrDrawTarget*) const { michael@0: return GrPathRenderer::kStencilOnly_StencilSupport; michael@0: } michael@0: michael@0: void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, michael@0: const SkStrokeRec& stroke, michael@0: GrDrawTarget* target) { michael@0: SkASSERT(!path.isInverseFillType()); michael@0: SkAutoTUnref p(fGpu->getContext()->createPath(path, stroke)); michael@0: target->stencilPath(p, path.getFillType()); michael@0: } michael@0: michael@0: bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, michael@0: const SkStrokeRec& stroke, michael@0: GrDrawTarget* target, michael@0: bool antiAlias) { michael@0: SkASSERT(!antiAlias); michael@0: SkASSERT(!stroke.isHairlineStyle()); michael@0: michael@0: GrDrawState* drawState = target->drawState(); michael@0: SkASSERT(drawState->getStencil().isDisabled()); michael@0: michael@0: SkAutoTUnref p(fGpu->getContext()->createPath(path, stroke)); michael@0: michael@0: if (path.isInverseFillType()) { michael@0: GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, michael@0: kZero_StencilOp, michael@0: kZero_StencilOp, michael@0: // We know our rect will hit pixels outside the clip and the user bits will be 0 michael@0: // outside the clip. So we can't just fill where the user bits are 0. We also need to michael@0: // check that the clip bit is set. michael@0: kEqualIfInClip_StencilFunc, michael@0: 0xffff, michael@0: 0x0000, michael@0: 0xffff); michael@0: michael@0: *drawState->stencil() = kInvertedStencilPass; michael@0: } else { michael@0: GR_STATIC_CONST_SAME_STENCIL(kStencilPass, michael@0: kZero_StencilOp, michael@0: kZero_StencilOp, michael@0: kNotEqual_StencilFunc, michael@0: 0xffff, michael@0: 0x0000, michael@0: 0xffff); michael@0: michael@0: *drawState->stencil() = kStencilPass; michael@0: } michael@0: michael@0: target->drawPath(p, path.getFillType()); michael@0: michael@0: target->drawState()->stencil()->setDisabled(); michael@0: return true; michael@0: }