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 GrAssert(NULL != context); 19 GrAssert(NULL != context->getGpu()); 20 if (context->getGpu()->caps()->pathStencilingSupport()) { 21 return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu())); 22 } else { 23 return NULL; 24 } 25 } 26 27 GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { 28 GrAssert(gpu->caps()->pathStencilingSupport()); 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.isFillStyle() && 42 !antiAlias && // doesn't do per-path AA, relies on the target having MSAA 43 target->getDrawState().getStencil().isDisabled(); 44 } 45 46 GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( 47 const SkPath&, 48 const SkStrokeRec& , 49 const GrDrawTarget*) const { 50 return GrPathRenderer::kStencilOnly_StencilSupport; 51 } 52 53 void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, 54 const SkStrokeRec& stroke, 55 GrDrawTarget* target) { 56 GrAssert(!path.isInverseFillType()); 57 SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 58 target->stencilPath(p, stroke, path.getFillType()); 59 } 60 61 bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, 62 const SkStrokeRec& stroke, 63 GrDrawTarget* target, 64 bool antiAlias) { 65 GrAssert(!antiAlias); 66 GrAssert(!stroke.isHairlineStyle()); 67 68 GrDrawState* drawState = target->drawState(); 69 GrAssert(drawState->getStencil().isDisabled()); 70 71 SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 72 73 SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType()); 74 target->stencilPath(p, stroke, nonInvertedFill); 75 76 // TODO: Use built in cover operation rather than a rect draw. This will require making our 77 // fragment shaders be able to eat varyings generated by a matrix. 78 79 // fill the path, zero out the stencil 80 SkRect bounds = p->getBounds(); 81 SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf; 82 GrDrawState::AutoViewMatrixRestore avmr; 83 84 if (nonInvertedFill == path.getFillType()) { 85 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 86 kZero_StencilOp, 87 kZero_StencilOp, 88 kNotEqual_StencilFunc, 89 0xffff, 90 0x0000, 91 0xffff); 92 *drawState->stencil() = kStencilPass; 93 } else { 94 GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, 95 kZero_StencilOp, 96 kZero_StencilOp, 97 // We know our rect will hit pixels outside the clip and the user bits will be 0 98 // outside the clip. So we can't just fill where the user bits are 0. We also need to 99 // check that the clip bit is set. 100 kEqualIfInClip_StencilFunc, 101 0xffff, 102 0x0000, 103 0xffff); 104 SkMatrix vmi; 105 bounds.setLTRB(0, 0, 106 SkIntToScalar(drawState->getRenderTarget()->width()), 107 SkIntToScalar(drawState->getRenderTarget()->height())); 108 // mapRect through persp matrix may not be correct 109 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { 110 vmi.mapRect(&bounds); 111 // theoretically could set bloat = 0, instead leave it because of matrix inversion 112 // precision. 113 } else { 114 avmr.setIdentity(drawState); 115 bloat = 0; 116 } 117 *drawState->stencil() = kInvertedStencilPass; 118 } 119 bounds.outset(bloat, bloat); 120 target->drawSimpleRect(bounds, NULL); 121 target->drawState()->stencil()->setDisabled(); 122 return true; 123 } 124