GrStencilAndCoverPathRenderer.cpp revision 80bacfeb4bda06541e8695bd502229727bccfea
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc. 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrStencilAndCoverPathRenderer.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrContext.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpu.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrPath.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) { 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(NULL != context); 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(NULL != context->getGpu()); 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (context->getGpu()->getCaps().pathStencilingSupport()) { 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu())); 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(gpu->getCaps().pathStencilingSupport()); 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fGpu = gpu; 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gpu->ref(); 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fGpu->unref(); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPathFill fill, 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrDrawTarget* target, 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool antiAlias) const { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kHairLine_GrPathFill != fill && 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru !antiAlias && // doesn't do per-path AA, relies on the target having MSAA 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->getDrawState().getStencil().isDisabled(); 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrStencilAndCoverPathRenderer::requiresStencilPass(const SkPath& path, 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPathFill fill, 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrDrawTarget* target) const { 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrStencilAndCoverPathRenderer::drawPathToStencil(const SkPath& path, 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPathFill fill, 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawTarget* target) { 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(kEvenOdd_GrPathFill == fill || kWinding_GrPathFill == fill); 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->stencilPath(p, fill); 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPathFill fill, 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawTarget* target, 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool antiAlias) { 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!antiAlias); 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(kHairLine_GrPathFill != fill); 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawState* drawState = target->drawState(); 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(drawState->getStencil().isDisabled()); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPathFill nonInvertedFill = GrNonInvertedFill(fill); 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->stencilPath(p, nonInvertedFill); 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // TODO: Use built in cover operation rather than a rect draw. This will require making our 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // fragment shaders be able to eat varyings generated by a matrix. 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // fill the path, zero out the stencil 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrRect bounds = p->getBounds(); 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrScalar bloat = drawState->getViewMatrix().getMaxStretch() * GR_ScalarHalf; 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawState::AutoDeviceCoordDraw adcd; 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (nonInvertedFill == fill) { 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kNotEqual_StencilFunc, 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff, 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0x0000, 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *drawState->stencil() = kStencilPass; 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // We know our rect will hit pixels outside the clip and the user bits will be 0 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // outside the clip. So we can't just fill where the user bits are 0. We also need to 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // check that the clip bit is set. 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kEqualIfInClip_StencilFunc, 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff, 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0x0000, 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff); 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrMatrix vmi; 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bounds.setLTRB(0, 0, 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrIntToScalar(drawState->getRenderTarget()->width()), 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrIntToScalar(drawState->getRenderTarget()->height())); 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // mapRect through persp matrix may not be correct 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru vmi.mapRect(&bounds); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // theoretically could set bloat = 0, instead leave it because of matrix inversion 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // precision. 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru adcd.set(drawState); 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bloat = 0; 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *drawState->stencil() = kInvertedStencilPass; 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bounds.outset(bloat, bloat); 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->drawSimpleRect(bounds, NULL); 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->drawState()->stencil()->setDisabled(); 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 121