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" 14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkStrokeRec.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) { 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(NULL != context); 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(NULL != context->getGpu()); 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (context->getGpu()->getCaps().pathStencilingSupport()) { 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu())); 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(gpu->getCaps().pathStencilingSupport()); 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fGpu = gpu; 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gpu->ref(); 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fGpu->unref(); 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, 37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkStrokeRec& stroke, 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrDrawTarget* target, 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool antiAlias) const { 40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return stroke.isFillStyle() && 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru !antiAlias && // doesn't do per-path AA, relies on the target having MSAA 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->getDrawState().getStencil().isDisabled(); 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( 46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkPath&, 47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkStrokeRec& , 48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const GrDrawTarget*) const { 49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return GrPathRenderer::kStencilOnly_StencilSupport; 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, 53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkStrokeRec& stroke, 54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger GrDrawTarget* target) { 55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger GrAssert(!path.isInverseFillType()); 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger target->stencilPath(p, stroke, path.getFillType()); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, 61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkStrokeRec& stroke, 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawTarget* target, 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool antiAlias) { 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!antiAlias); 65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger GrAssert(!stroke.isHairlineStyle()); 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawState* drawState = target->drawState(); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(drawState->getStencil().isDisabled()); 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<GrPath> p(fGpu->createPath(path)); 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType()); 73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger target->stencilPath(p, stroke, nonInvertedFill); 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // TODO: Use built in cover operation rather than a rect draw. This will require making our 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // fragment shaders be able to eat varyings generated by a matrix. 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // fill the path, zero out the stencil 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrRect bounds = p->getBounds(); 80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf; 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrDrawState::AutoDeviceCoordDraw adcd; 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if (nonInvertedFill == path.getFillType()) { 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kNotEqual_StencilFunc, 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff, 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0x0000, 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff); 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *drawState->stencil() = kStencilPass; 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kZero_StencilOp, 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // We know our rect will hit pixels outside the clip and the user bits will be 0 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // outside the clip. So we can't just fill where the user bits are 0. We also need to 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // check that the clip bit is set. 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kEqualIfInClip_StencilFunc, 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff, 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0x0000, 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0xffff); 103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkMatrix vmi; 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bounds.setLTRB(0, 0, 105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkIntToScalar(drawState->getRenderTarget()->width()), 106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkIntToScalar(drawState->getRenderTarget()->height())); 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // mapRect through persp matrix may not be correct 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru vmi.mapRect(&bounds); 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // theoretically could set bloat = 0, instead leave it because of matrix inversion 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // precision. 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru adcd.set(drawState); 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bloat = 0; 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *drawState->stencil() = kInvertedStencilPass; 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bounds.outset(bloat, bloat); 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->drawSimpleRect(bounds, NULL); 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru target->drawState()->stencil()->setDisabled(); 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 123