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 "GrDrawTargetCaps.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpu.h"
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "GrPath.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStrokeRec.h"
16910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != context);
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != context->getGpu());
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (context->getGpu()->caps()->pathRenderingSupport()) {
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu()));
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) {
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(gpu->caps()->pathRenderingSupport());
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fGpu = gpu;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    gpu->ref();
310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger}
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGpu->unref();
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                const SkStrokeRec& stroke,
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                const GrDrawTarget* target,
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                bool antiAlias) const {
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return !stroke.isHairlineStyle() &&
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           NULL != target->getDrawState().getRenderTarget()->getStencilBuffer() &&
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           target->getDrawState().getStencil().isDisabled();
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                        const SkPath&,
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                        const SkStrokeRec& ,
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                        const GrDrawTarget*) const {
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return GrPathRenderer::kStencilOnly_StencilSupport;
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                  const SkStrokeRec& stroke,
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                                  GrDrawTarget* target) {
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(!path.isInverseFillType());
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke));
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    target->stencilPath(p, path.getFillType());
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                               const SkStrokeRec& stroke,
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                               GrDrawTarget* target,
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                               bool antiAlias) {
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(!antiAlias);
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(!stroke.isHairlineStyle());
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrDrawState* drawState = target->drawState();
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(drawState->getStencil().isDisabled());
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke));
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (path.isInverseFillType()) {
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kZero_StencilOp,
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kZero_StencilOp,
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // We know our rect will hit pixels outside the clip and the user bits will be 0
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // outside the clip. So we can't just fill where the user bits are 0. We also need to
80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // check that the clip bit is set.
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kEqualIfInClip_StencilFunc,
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            0xffff,
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            0x0000,
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            0xffff);
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *drawState->stencil() = kInvertedStencilPass;
870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    } else {
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            kZero_StencilOp,
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            kZero_StencilOp,
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            kNotEqual_StencilFunc,
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            0xffff,
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            0x0000,
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            0xffff);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *drawState->stencil() = kStencilPass;
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawPath(p, path.getFillType());
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    target->drawState()->stencil()->setDisabled();
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger