1 2 /* 3 * Copyright 2012 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "GrStencilAndCoverPathRenderer.h" 11 #include "GrContext.h" 12 #include "GrDrawTargetCaps.h" 13 #include "GrGpu.h" 14 #include "GrPath.h" 15 #include "SkStrokeRec.h" 16 17 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) { 18 SkASSERT(NULL != context); 19 SkASSERT(NULL != context->getGpu()); 20 if (context->getGpu()->caps()->pathRenderingSupport()) { 21 return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu())); 22 } else { 23 return NULL; 24 } 25 } 26 27 GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { 28 SkASSERT(gpu->caps()->pathRenderingSupport()); 29 fGpu = gpu; 30 gpu->ref(); 31 } 32 33 GrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { 34 fGpu->unref(); 35 } 36 37 bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, 38 const SkStrokeRec& stroke, 39 const GrDrawTarget* target, 40 bool antiAlias) const { 41 return !stroke.isHairlineStyle() && 42 !antiAlias && // doesn't do per-path AA, relies on the target having MSAA 43 NULL != target->getDrawState().getRenderTarget()->getStencilBuffer() && 44 target->getDrawState().getStencil().isDisabled(); 45 } 46 47 GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( 48 const SkPath&, 49 const SkStrokeRec& , 50 const GrDrawTarget*) const { 51 return GrPathRenderer::kStencilOnly_StencilSupport; 52 } 53 54 void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, 55 const SkStrokeRec& stroke, 56 GrDrawTarget* target) { 57 SkASSERT(!path.isInverseFillType()); 58 SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke)); 59 target->stencilPath(p, path.getFillType()); 60 } 61 62 bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, 63 const SkStrokeRec& stroke, 64 GrDrawTarget* target, 65 bool antiAlias) { 66 SkASSERT(!antiAlias); 67 SkASSERT(!stroke.isHairlineStyle()); 68 69 GrDrawState* drawState = target->drawState(); 70 SkASSERT(drawState->getStencil().isDisabled()); 71 72 SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke)); 73 74 if (path.isInverseFillType()) { 75 GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, 76 kZero_StencilOp, 77 kZero_StencilOp, 78 // We know our rect will hit pixels outside the clip and the user bits will be 0 79 // outside the clip. So we can't just fill where the user bits are 0. We also need to 80 // check that the clip bit is set. 81 kEqualIfInClip_StencilFunc, 82 0xffff, 83 0x0000, 84 0xffff); 85 86 *drawState->stencil() = kInvertedStencilPass; 87 } else { 88 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 89 kZero_StencilOp, 90 kZero_StencilOp, 91 kNotEqual_StencilFunc, 92 0xffff, 93 0x0000, 94 0xffff); 95 96 *drawState->stencil() = kStencilPass; 97 } 98 99 target->drawPath(p, path.getFillType()); 100 101 target->drawState()->stencil()->setDisabled(); 102 return true; 103 } 104