1ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
2ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com/*
3ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com * Copyright 2012 Google Inc.
4ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com *
5ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
6ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com * found in the LICENSE file.
7ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com */
8ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
9ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
10ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com#include "GrStencilAndCoverPathRenderer.h"
11ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com#include "GrContext.h"
12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h"
13ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com#include "GrGpu.h"
14ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com#include "GrPath.h"
155f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
16ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
17ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.comGrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
1849f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(context);
1949f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(context->getGpu());
20c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org    if (context->getGpu()->caps()->pathRenderingSupport()) {
21c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu()));
22ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    } else {
23ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        return NULL;
24ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    }
25ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
26ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
27ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.comGrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) {
28c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org    SkASSERT(gpu->caps()->pathRenderingSupport());
29ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    fGpu = gpu;
30ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    gpu->ref();
31ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
32ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
33ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.comGrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() {
34ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    fGpu->unref();
35ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
36ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
37e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
38e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                                const SkStrokeRec& stroke,
39ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com                                                const GrDrawTarget* target,
40ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com                                                bool antiAlias) const {
4132184d81629e39809bb9e915286d8fe971a8ed68commit-bot@chromium.org    return !stroke.isHairlineStyle() &&
42ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com           !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
4349f085dddff10473b6ebf832a974288300224e60bsalomon           target->getDrawState().getRenderTarget()->getStencilBuffer() &&
44ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com           target->getDrawState().getStencil().isDisabled();
45ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
46ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
4745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.comGrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
48e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                                        const SkPath&,
495f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com                                                        const SkStrokeRec& ,
5045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                        const GrDrawTarget*) const {
5145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com    return GrPathRenderer::kStencilOnly_StencilSupport;
52ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
53ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
544e205b10799730b887ae5d6ac7207570292c177fcdaltonstatic GrPath* get_gr_path(GrGpu* gpu, const SkPath& skPath, const SkStrokeRec& stroke) {
554e205b10799730b887ae5d6ac7207570292c177fcdalton    GrContext* ctx = gpu->getContext();
564e205b10799730b887ae5d6ac7207570292c177fcdalton    GrResourceKey resourceKey = GrPath::ComputeKey(skPath, stroke);
574e205b10799730b887ae5d6ac7207570292c177fcdalton    SkAutoTUnref<GrPath> path(static_cast<GrPath*>(ctx->findAndRefCachedResource(resourceKey)));
584e205b10799730b887ae5d6ac7207570292c177fcdalton    if (NULL == path || !path->isEqualTo(skPath, stroke)) {
594e205b10799730b887ae5d6ac7207570292c177fcdalton        path.reset(gpu->pathRendering()->createPath(skPath, stroke));
604e205b10799730b887ae5d6ac7207570292c177fcdalton        ctx->addResourceToCache(resourceKey, path);
614e205b10799730b887ae5d6ac7207570292c177fcdalton    }
624e205b10799730b887ae5d6ac7207570292c177fcdalton    return path.detach();
634e205b10799730b887ae5d6ac7207570292c177fcdalton}
644e205b10799730b887ae5d6ac7207570292c177fcdalton
65e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.comvoid GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
66e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                                  const SkStrokeRec& stroke,
6745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                  GrDrawTarget* target) {
68e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    SkASSERT(!path.isInverseFillType());
694e205b10799730b887ae5d6ac7207570292c177fcdalton    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
70e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    target->stencilPath(p, path.getFillType());
71ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
72ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
73e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
74e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                               const SkStrokeRec& stroke,
75ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com                                               GrDrawTarget* target,
760f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com                                               bool antiAlias) {
77f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!antiAlias);
78f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!stroke.isHairlineStyle());
79ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
80ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    GrDrawState* drawState = target->drawState();
81f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(drawState->getStencil().isDisabled());
82ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com
834e205b10799730b887ae5d6ac7207570292c177fcdalton    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
840f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com
856803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org    if (path.isInverseFillType()) {
86ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
87ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com            kZero_StencilOp,
88ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com            kZero_StencilOp,
8905a718c9d2302b08f859adac5854b2df6ff84e43bsalomon@google.com            // We know our rect will hit pixels outside the clip and the user bits will be 0
9005a718c9d2302b08f859adac5854b2df6ff84e43bsalomon@google.com            // outside the clip. So we can't just fill where the user bits are 0. We also need to
9105a718c9d2302b08f859adac5854b2df6ff84e43bsalomon@google.com            // check that the clip bit is set.
9205a718c9d2302b08f859adac5854b2df6ff84e43bsalomon@google.com            kEqualIfInClip_StencilFunc,
93ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com            0xffff,
94ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com            0x0000,
95ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com            0xffff);
96c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org
97ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        *drawState->stencil() = kInvertedStencilPass;
98c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org    } else {
99c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org        GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
100c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            kZero_StencilOp,
101c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            kZero_StencilOp,
102c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            kNotEqual_StencilFunc,
103c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            0xffff,
104c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            0x0000,
105c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org            0xffff);
106c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org
107c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org        *drawState->stencil() = kStencilPass;
108ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    }
109c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org
110e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    target->drawPath(p, path.getFillType());
111c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org
112ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    target->drawState()->stencil()->setDisabled();
113ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com    return true;
114ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com}
115