GrSoftwarePathRenderer.cpp revision 12b4e27ae1a29460e91a59f38122483e1faec697
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"
12f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
13ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
14f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.combool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
1512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                         const SkStroke& stroke,
16f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                         const GrDrawTarget* target,
17f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                         bool antiAlias) const {
18ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    if (!antiAlias || NULL == fContext) {
19ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        // TODO: We could allow the SW path to also handle non-AA paths but
20ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        // this would mean that GrDefaultPathRenderer would never be called
21ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        // (since it appears after the SW renderer in the path renderer
22d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        // chain). Some testing would need to be done r.e. performance
23ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        // and consistency of the resulting images before removing
24ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        // the "!antiAlias" clause from the above test
25f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com        return false;
26f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com    }
27f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
28ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    return true;
29ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
30ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
31ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comnamespace {
32ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
33ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
34ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// gets device coord bounds of path (not considering the fill) and clip. The
35d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com// path bounds will be a subset of the clip bounds. returns false if
36ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// path bounds would be empty.
37ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.combool get_path_and_clip_bounds(const GrDrawTarget* target,
38ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com                              const SkPath& path,
39b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                              const SkMatrix& matrix,
407b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                              GrIRect* devPathBounds,
417b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                              GrIRect* devClipBounds) {
42ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    // compute bounds as intersection of rt size, clip, and path
43ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
44ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    if (NULL == rt) {
45ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
46ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
477b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    *devPathBounds = GrIRect::MakeWH(rt->width(), rt->height());
483e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
497b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    target->getClip()->getConservativeBounds(rt, devClipBounds);
507b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com
51d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    // TODO: getConservativeBounds already intersects with the
527b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    // render target's bounding box. Remove this next line
537b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (!devPathBounds->intersect(*devClipBounds)) {
543e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com        return false;
55ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
563e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com
57366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com    if (!path.getBounds().isEmpty()) {
58366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com        GrRect pathSBounds;
59366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com        matrix.mapRect(&pathSBounds, path.getBounds());
60ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        GrIRect pathIBounds;
61ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        pathSBounds.roundOut(&pathIBounds);
627b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        if (!devPathBounds->intersect(pathIBounds)) {
63276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com            // set the correct path bounds, as this would be used later.
647b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            *devPathBounds = pathIBounds;
65ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com            return false;
66ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        }
67ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    } else {
687b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        *devPathBounds = GrIRect::EmptyIRect();
69ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
70ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
71ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    return true;
72ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
73ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
74ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
75ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.comvoid draw_around_inv_path(GrDrawTarget* target,
767b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                          const GrIRect& devClipBounds,
777b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                          const GrIRect& devPathBounds) {
785b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
79e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    if (!adcd.succeeded()) {
80e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return;
81e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
82ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    GrRect rect;
837b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fTop < devPathBounds.fTop) {
84d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
857b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devPathBounds.fTop);
86e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        target->drawSimpleRect(rect, NULL);
87ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
887b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fLeft < devPathBounds.fLeft) {
89d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
907b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devPathBounds.fLeft, devPathBounds.fBottom);
91e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        target->drawSimpleRect(rect, NULL);
92ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
937b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fRight > devPathBounds.fRight) {
94d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devPathBounds.fRight, devPathBounds.fTop,
957b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devPathBounds.fBottom);
96e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        target->drawSimpleRect(rect, NULL);
97ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
987b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (devClipBounds.fBottom > devPathBounds.fBottom) {
99d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
1007b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                  devClipBounds.fRight, devClipBounds.fBottom);
101e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        target->drawSimpleRect(rect, NULL);
102ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
103f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com}
104f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
105ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com}
106ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
107ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
108ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com// return true on success; false on failure
109f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.combool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
11012b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                        const SkStroke& stroke,
111f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                        GrDrawTarget* target,
112f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com                                        bool antiAlias) {
113f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com
114ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    if (NULL == fContext) {
115ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com        return false;
116ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
117ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
118366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com    GrDrawState* drawState = target->drawState();
119366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com
120b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix vm = drawState->getViewMatrix();
121366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com
1227b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    GrIRect devPathBounds, devClipBounds;
123366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com    if (!get_path_and_clip_bounds(target, path, vm,
1247b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                                  &devPathBounds, &devClipBounds)) {
12512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        if (path.isInverseFillType()) {
1267b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            draw_around_inv_path(target, devClipBounds, devPathBounds);
127276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com        }
128276c1fabc22d4980c2ed8fe879f6510289b87cdebsalomon@google.com        return true;
129ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
130366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com
1315dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    SkAutoTUnref<GrTexture> texture(
13212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
13312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                                  devPathBounds,
1345dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com                                                  antiAlias, &vm));
1355dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    if (NULL == texture) {
1365dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com        return false;
137ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com    }
138ed4155d610442b75e906a3489c984394c34b5ff9robertphillips@google.com
1397b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
1405dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com
14112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    if (path.isInverseFillType()) {
1427b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        draw_around_inv_path(target, devClipBounds, devPathBounds);
1435dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    }
1445dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com
1455dfb67219a308edecafbe09eebb35c5e149db6e6robertphillips@google.com    return true;
146f4c2c527dd3cab979621fdfbc07eb22fee103472robertphillips@google.com}
147