summaryrefslogtreecommitdiff
path: root/gpu/GrStencilAndCoverPathRenderer.cpp
diff options
context:
space:
mode:
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-28 18:48:06 +0000
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-28 18:48:06 +0000
commit8dc33d06f5759d2e587dbd266226fc0fe0c1562b (patch)
treed99373b2a55a3e6d1bb1a7ab882bd0d73a153a75 /gpu/GrStencilAndCoverPathRenderer.cpp
parent6c6c379603a72ec87bd1fc51b40a01a9332e8feb (diff)
downloadsrc-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.cpp130
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;
+}