diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-28 18:48:06 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-28 18:48:06 +0000 |
commit | 8dc33d06f5759d2e587dbd266226fc0fe0c1562b (patch) | |
tree | d99373b2a55a3e6d1bb1a7ab882bd0d73a153a75 /gpu/GrStencilAndCoverPathRenderer.cpp | |
parent | 6c6c379603a72ec87bd1fc51b40a01a9332e8feb (diff) | |
download | src-8dc33d06f5759d2e587dbd266226fc0fe0c1562b.tar.gz |
Initial support for GL_NV_path_renering. Experimental, there are still some issues to resolve, set gyp variable skia_nv_path_rendering=1 or build flag GR_GL_USE_NV_PATH_RENDERING to enable.
http://codereview.appspot.com/6349049/
git-svn-id: http://skia.googlecode.com/svn/trunk/src@4390 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/GrStencilAndCoverPathRenderer.cpp')
-rw-r--r-- | gpu/GrStencilAndCoverPathRenderer.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/gpu/GrStencilAndCoverPathRenderer.cpp b/gpu/GrStencilAndCoverPathRenderer.cpp new file mode 100644 index 00000000..40d998b6 --- /dev/null +++ b/gpu/GrStencilAndCoverPathRenderer.cpp @@ -0,0 +1,130 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "GrStencilAndCoverPathRenderer.h" +#include "GrContext.h" +#include "GrGpu.h" +#include "GrPath.h" + +GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) { + GrAssert(NULL != context); + GrAssert(NULL != context->getGpu()); + if (context->getGpu()->getCaps().fPathStencilingSupport) { + return new GrStencilAndCoverPathRenderer(context->getGpu()); + } else { + return NULL; + } +} + +GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) { + GrAssert(gpu->getCaps().fPathStencilingSupport); + fGpu = gpu; + gpu->ref(); +} + +GrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { + fGpu->unref(); +} + +bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, + GrPathFill fill, + const GrDrawTarget* target, + bool antiAlias) const { + return kHairLine_GrPathFill != fill && + !antiAlias && // doesn't do per-path AA, relies on the target having MSAA + target->getDrawState().getStencil().isDisabled(); +} + +bool GrStencilAndCoverPathRenderer::requiresStencilPass(const SkPath& path, + GrPathFill fill, + const GrDrawTarget* target) const { + return true; +} + +void GrStencilAndCoverPathRenderer::drawPathToStencil(const SkPath& path, + GrPathFill fill, + GrDrawTarget* target) { + GrAssert(kEvenOdd_GrPathFill == fill || kWinding_GrPathFill == fill); + SkAutoTUnref<GrPath> p(fGpu->createPath(path)); + target->stencilPath(p, fill); +} + +bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, + GrPathFill fill, + const GrVec* translate, + GrDrawTarget* target, + GrDrawState::StageMask stageMask, + bool antiAlias){ + GrAssert(!antiAlias); + GrAssert(kHairLine_GrPathFill != fill); + + GrDrawState* drawState = target->drawState(); + GrAssert(drawState->getStencil().isDisabled()); + + SkAutoTUnref<GrPath> p(fGpu->createPath(path)); + GrDrawState::AutoViewMatrixRestore avmr; + if (translate) { + avmr.set(drawState); + drawState->viewMatrix()->postTranslate(translate->fX, translate->fY); + } + GrPathFill nonInvertedFill = GrNonInvertedFill(fill); + target->stencilPath(p, nonInvertedFill); + + // TODO: Use built in cover operation rather than a rect draw. This will require making our + // fragment shaders be able to eat varyings generated by a matrix. + + // fill the path, zero out the stencil + GrRect bounds = p->getBounds(); + GrScalar bloat = drawState->getViewMatrix().getMaxStretch() * GR_ScalarHalf; + if (nonInvertedFill == fill) { + GR_STATIC_CONST_SAME_STENCIL(kStencilPass, + kZero_StencilOp, + kZero_StencilOp, + kNotEqual_StencilFunc, + 0xffff, + 0x0000, + 0xffff); + *drawState->stencil() = kStencilPass; + } else { + GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, + kZero_StencilOp, + kZero_StencilOp, + kEqual_StencilFunc, + 0xffff, + 0x0000, + 0xffff); + GrMatrix vmi; + bounds.setLTRB(0, 0, + GrIntToScalar(drawState->getRenderTarget()->width()), + GrIntToScalar(drawState->getRenderTarget()->height())); + // mapRect through persp matrix may not be correct + if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { + vmi.mapRect(&bounds); + // theoretically could set bloat = 0, instead leave it because of matrix inversion precision. + } else { + if (stageMask) { + if (!drawState->getViewInverse(&vmi)) { + GrPrintf("Could not invert matrix."); + return false; + } + drawState->preConcatSamplerMatrices(stageMask, vmi); + } + if (avmr.isSet()) { + avmr.set(drawState); + } + drawState->viewMatrix()->reset(); + bloat = 0; + } + *drawState->stencil() = kInvertedStencilPass; + } + bounds.outset(bloat, bloat); + target->drawSimpleRect(bounds, NULL, stageMask); + target->drawState()->stencil()->setDisabled(); + return true; +} |