1f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
2f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com/*
3f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * Copyright 2012 Google Inc.
4f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com *
5f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
6f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com * found in the LICENSE file.
7f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com */
8f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
9f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com#include "GrSoftwarePathRenderer.h"
10ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com#include "GrContext.h"
1158b20215f6d88b7e1cacae0b76226fced5109293robertphillips@google.com#include "GrSWMaskHelper.h"
1272e3ae486c66871c2043eac4f08d85d419fbca2absalomon#include "GrVertexBuffer.h"
13f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
14ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
159853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrSoftwarePathRenderer::canDrawPath(const GrDrawTarget*,
168dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                                         const GrPipelineBuilder*,
178059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                         const SkMatrix& viewMatrix,
189853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                         const SkPath&,
191899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                         const GrStrokeInfo& stroke,
20f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                         bool antiAlias) const {
21730c0447916909f01df7fa12e9c82dd7cf7989dcrobertphillips    if (NULL == fContext) {
22f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com        return false;
23f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com    }
241899651ffc459f5462aa989cd6d08507947b67e4kkinnunen    if (stroke.isDashed()) {
251899651ffc459f5462aa989cd6d08507947b67e4kkinnunen        return false;
261899651ffc459f5462aa989cd6d08507947b67e4kkinnunen    }
27ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    return true;
28ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
29ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
309853ccef19c200be93a6211f32589fa82a53067cjoshualittGrPathRenderer::StencilSupport
319853ccef19c200be93a6211f32589fa82a53067cjoshualittGrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
328dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                                            const GrPipelineBuilder*,
339853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                            const SkPath&,
341899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                            const GrStrokeInfo&) const {
3545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com    return GrPathRenderer::kNoSupport_StencilSupport;
3645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com}
3745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com
38ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comnamespace {
39ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
40ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
41ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// gets device coord bounds of path (not considering the fill) and clip. The
42d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com// path bounds will be a subset of the clip bounds. returns false if
43ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// path bounds would be empty.
44ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.combool get_path_and_clip_bounds(const GrDrawTarget* target,
458dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                              const GrPipelineBuilder* pipelineBuilder,
46ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com                              const SkPath& path,
47b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                              const SkMatrix& matrix,
48fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                              SkIRect* devPathBounds,
49fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                              SkIRect* devClipBounds) {
50ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    // compute bounds as intersection of rt size, clip, and path
518dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel    const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
52ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    if (NULL == rt) {
53ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
54ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
553e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
5644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    pipelineBuilder->clip().getConservativeBounds(rt, devClipBounds);
577b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com
58e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips    if (devClipBounds->isEmpty()) {
59e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips        *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
603e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com        return false;
61ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
623e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
63366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com    if (!path.getBounds().isEmpty()) {
64fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        SkRect pathSBounds;
65366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com        matrix.mapRect(&pathSBounds, path.getBounds());
66fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        SkIRect pathIBounds;
67ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        pathSBounds.roundOut(&pathIBounds);
68e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips        *devPathBounds = *devClipBounds;
697b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        if (!devPathBounds->intersect(pathIBounds)) {
70276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com            // set the correct path bounds, as this would be used later.
717b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            *devPathBounds = pathIBounds;
72ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com            return false;
73ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        }
74ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    } else {
75fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org        *devPathBounds = SkIRect::EmptyIRect();
76ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
77ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
78ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    return true;
79ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
80ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
81ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
82ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comvoid draw_around_inv_path(GrDrawTarget* target,
838dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                          GrPipelineBuilder* pipelineBuilder,
842e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                          GrColor color,
858059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                          const SkMatrix& viewMatrix,
86fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                          const SkIRect& devClipBounds,
87fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                          const SkIRect& devPathBounds) {
88d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    SkMatrix invert;
898059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt    if (!viewMatrix.invert(&invert)) {
90e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return;
91e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
92d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt
93fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkRect rect;
947b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fTop < devPathBounds.fTop) {
95d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
967b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devPathBounds.fTop);
978dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
98ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
997b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fLeft < devPathBounds.fLeft) {
100d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
1017b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devPathBounds.fLeft, devPathBounds.fBottom);
1028dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
103ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
1047b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fRight > devPathBounds.fRight) {
105d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devPathBounds.fRight, devPathBounds.fTop,
1067b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devPathBounds.fBottom);
1078dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
108ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
1097b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fBottom > devPathBounds.fBottom) {
110d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
1117b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devClipBounds.fBottom);
1128dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel        target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
113ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
114f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com}
115f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
116ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
117ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
118ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
119ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// return true on success; false on failure
1209853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target,
1218dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                                        GrPipelineBuilder* pipelineBuilder,
1222e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                        GrColor color,
1238059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                        const SkMatrix& viewMatrix,
1249853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                        const SkPath& path,
1251899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                        const GrStrokeInfo& stroke,
126f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                        bool antiAlias) {
127ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    if (NULL == fContext) {
128ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
129ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
130ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
131fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkIRect devPathBounds, devClipBounds;
13244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt    if (!get_path_and_clip_bounds(target, pipelineBuilder, path, viewMatrix, &devPathBounds,
13344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt                                  &devClipBounds)) {
134e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com        if (path.isInverseFillType()) {
1358dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel            draw_around_inv_path(target, pipelineBuilder, color, viewMatrix, devClipBounds,
1368dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                                 devPathBounds);
137276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com        }
138276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com        return true;
139ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
140366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com
1415dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    SkAutoTUnref<GrTexture> texture(
1421899651ffc459f5462aa989cd6d08507947b67e4kkinnunen            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke.getStrokeRec(),
14312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                                  devPathBounds,
1448059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                  antiAlias, &viewMatrix));
1455dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    if (NULL == texture) {
1465dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com        return false;
147ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
148ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
1498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel    GrPipelineBuilder copy = *pipelineBuilder;
1508059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt    GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, &copy, color, viewMatrix,
1518059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                             devPathBounds);
1525dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com
153e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    if (path.isInverseFillType()) {
1548dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel        draw_around_inv_path(target, pipelineBuilder, color, viewMatrix, devClipBounds,
1558dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                             devPathBounds);
1565dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    }
1575dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com
1585dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    return true;
159f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com}
160