| OLD | NEW |
| (Empty) |
| 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 "GrCaps.h" | |
| 12 #include "GrContext.h" | |
| 13 #include "GrGpu.h" | |
| 14 #include "GrPath.h" | |
| 15 #include "GrRenderTarget.h" | |
| 16 #include "GrResourceProvider.h" | |
| 17 #include "GrStrokeInfo.h" | |
| 18 | |
| 19 /* | |
| 20 * For now paths only natively support winding and even odd fill types | |
| 21 */ | |
| 22 static GrPathRendering::FillType convert_skpath_filltype(SkPath::FillType fill)
{ | |
| 23 switch (fill) { | |
| 24 default: | |
| 25 SkFAIL("Incomplete Switch\n"); | |
| 26 case SkPath::kWinding_FillType: | |
| 27 case SkPath::kInverseWinding_FillType: | |
| 28 return GrPathRendering::kWinding_FillType; | |
| 29 case SkPath::kEvenOdd_FillType: | |
| 30 case SkPath::kInverseEvenOdd_FillType: | |
| 31 return GrPathRendering::kEvenOdd_FillType; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resour
ceProvider, | |
| 36 const GrCaps& caps) { | |
| 37 if (caps.shaderCaps()->pathRenderingSupport()) { | |
| 38 return new GrStencilAndCoverPathRenderer(resourceProvider); | |
| 39 } else { | |
| 40 return nullptr; | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider*
resourceProvider) | |
| 45 : fResourceProvider(resourceProvider) { | |
| 46 } | |
| 47 | |
| 48 bool GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c
onst { | |
| 49 if (args.fStroke->isHairlineStyle()) { | |
| 50 return false; | |
| 51 } | |
| 52 if (!args.fPipelineBuilder->getStencil().isDisabled()) { | |
| 53 return false; | |
| 54 } | |
| 55 if (args.fAntiAlias) { | |
| 56 return args.fPipelineBuilder->getRenderTarget()->isStencilBufferMultisam
pled(); | |
| 57 } else { | |
| 58 return true; // doesn't do per-path AA, relies on the target having MSAA | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 static GrPath* get_gr_path(GrResourceProvider* resourceProvider, const SkPath& s
kPath, | |
| 63 const GrStrokeInfo& stroke) { | |
| 64 GrUniqueKey key; | |
| 65 bool isVolatile; | |
| 66 GrPath::ComputeKey(skPath, stroke, &key, &isVolatile); | |
| 67 SkAutoTUnref<GrPath> path( | |
| 68 static_cast<GrPath*>(resourceProvider->findAndRefResourceByUniqueKey(key
))); | |
| 69 if (!path) { | |
| 70 path.reset(resourceProvider->createPath(skPath, stroke)); | |
| 71 if (!isVolatile) { | |
| 72 resourceProvider->assignUniqueKeyToResource(key, path); | |
| 73 } | |
| 74 } else { | |
| 75 SkASSERT(path->isEqualTo(skPath, stroke)); | |
| 76 } | |
| 77 return path.detach(); | |
| 78 } | |
| 79 | |
| 80 void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) { | |
| 81 SkASSERT(!args.fPath->isInverseFillType()); | |
| 82 SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(GrColor_WHITE, *arg
s.fViewMatrix)); | |
| 83 SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, *args.fPath, *args.fSt
roke)); | |
| 84 args.fTarget->stencilPath(*args.fPipelineBuilder, pp, p, | |
| 85 convert_skpath_filltype(args.fPath->getFillType())
); | |
| 86 } | |
| 87 | |
| 88 bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { | |
| 89 SkASSERT(!args.fStroke->isHairlineStyle()); | |
| 90 const SkPath& path = *args.fPath; | |
| 91 GrPipelineBuilder* pipelineBuilder = args.fPipelineBuilder; | |
| 92 const SkMatrix& viewMatrix = *args.fViewMatrix; | |
| 93 | |
| 94 SkASSERT(pipelineBuilder->getStencil().isDisabled()); | |
| 95 | |
| 96 if (args.fAntiAlias) { | |
| 97 SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled
()); | |
| 98 pipelineBuilder->enableState(GrPipelineBuilder::kHWAntialias_Flag); | |
| 99 } | |
| 100 | |
| 101 SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, path, *args.fStroke)); | |
| 102 | |
| 103 if (path.isInverseFillType()) { | |
| 104 GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, | |
| 105 kKeep_StencilOp, | |
| 106 kZero_StencilOp, | |
| 107 // We know our rect will hit pixels outside the clip and the user bi
ts will be 0 | |
| 108 // outside the clip. So we can't just fill where the user bits are 0
. We also need to | |
| 109 // check that the clip bit is set. | |
| 110 kEqualIfInClip_StencilFunc, | |
| 111 0xffff, | |
| 112 0x0000, | |
| 113 0xffff); | |
| 114 | |
| 115 pipelineBuilder->setStencil(kInvertedStencilPass); | |
| 116 | |
| 117 // fake inverse with a stencil and cover | |
| 118 SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(GrColor_WHITE,
viewMatrix)); | |
| 119 args.fTarget->stencilPath(*pipelineBuilder, pp, p, | |
| 120 convert_skpath_filltype(path.getFillType())); | |
| 121 | |
| 122 SkMatrix invert = SkMatrix::I(); | |
| 123 SkRect bounds = | |
| 124 SkRect::MakeLTRB(0, 0, SkIntToScalar(pipelineBuilder->getRenderTarge
t()->width()), | |
| 125 SkIntToScalar(pipelineBuilder->getRenderTarget()->h
eight())); | |
| 126 SkMatrix vmi; | |
| 127 // mapRect through persp matrix may not be correct | |
| 128 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) { | |
| 129 vmi.mapRect(&bounds); | |
| 130 // theoretically could set bloat = 0, instead leave it because of ma
trix inversion | |
| 131 // precision. | |
| 132 SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf; | |
| 133 bounds.outset(bloat, bloat); | |
| 134 } else { | |
| 135 if (!viewMatrix.invert(&invert)) { | |
| 136 return false; | |
| 137 } | |
| 138 } | |
| 139 const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : vi
ewMatrix; | |
| 140 args.fTarget->drawNonAARect(*pipelineBuilder, args.fColor, viewM, bounds
, invert); | |
| 141 } else { | |
| 142 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | |
| 143 kZero_StencilOp, | |
| 144 kKeep_StencilOp, | |
| 145 kNotEqual_StencilFunc, | |
| 146 0xffff, | |
| 147 0x0000, | |
| 148 0xffff); | |
| 149 | |
| 150 pipelineBuilder->setStencil(kStencilPass); | |
| 151 SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(args.fColor, vi
ewMatrix)); | |
| 152 args.fTarget->drawPath(*pipelineBuilder, pp, p, | |
| 153 convert_skpath_filltype(path.getFillType())); | |
| 154 } | |
| 155 | |
| 156 pipelineBuilder->stencil()->setDisabled(); | |
| 157 return true; | |
| 158 } | |
| OLD | NEW |