blob: 466ad817793a19aadff9613f2c52f9fcac02f8ce [file] [log] [blame]
robertphillips@google.comf4c2c522012-04-27 12:08:47 +00001
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "GrSoftwarePathRenderer.h"
robertphillips@google.comed4155d2012-05-01 14:30:24 +000010#include "GrContext.h"
robertphillips@google.com58b20212012-06-27 20:44:52 +000011#include "GrSWMaskHelper.h"
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000012
robertphillips@google.comed4155d2012-05-01 14:30:24 +000013////////////////////////////////////////////////////////////////////////////////
joshualitt9853cce2014-11-17 14:22:48 -080014bool GrSoftwarePathRenderer::canDrawPath(const GrDrawTarget*,
egdaniel8dd688b2015-01-22 10:16:09 -080015 const GrPipelineBuilder*,
joshualitt8059eb92014-12-29 15:10:07 -080016 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -080017 const SkPath&,
robertphillips@google.come79f3202014-02-11 16:30:21 +000018 const SkStrokeRec&,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000019 bool antiAlias) const {
robertphillips730c0442014-07-25 05:52:38 -070020 if (NULL == fContext) {
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000021 return false;
22 }
23
robertphillips@google.comed4155d2012-05-01 14:30:24 +000024 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000025}
26
joshualitt9853cce2014-11-17 14:22:48 -080027GrPathRenderer::StencilSupport
28GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
egdaniel8dd688b2015-01-22 10:16:09 -080029 const GrPipelineBuilder*,
joshualitt9853cce2014-11-17 14:22:48 -080030 const SkPath&,
31 const SkStrokeRec&) const {
bsalomon@google.com45a15f52012-12-10 19:10:17 +000032 return GrPathRenderer::kNoSupport_StencilSupport;
33}
34
robertphillips@google.comed4155d2012-05-01 14:30:24 +000035namespace {
36
37////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000038// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000039// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000040// path bounds would be empty.
41bool get_path_and_clip_bounds(const GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080042 const GrPipelineBuilder* pipelineBuilder,
robertphillips@google.comed4155d2012-05-01 14:30:24 +000043 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000044 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000045 SkIRect* devPathBounds,
46 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000047 // compute bounds as intersection of rt size, clip, and path
egdaniel8dd688b2015-01-22 10:16:09 -080048 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000049 if (NULL == rt) {
50 return false;
51 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000052
joshualitt44701df2015-02-23 14:44:57 -080053 pipelineBuilder->clip().getConservativeBounds(rt, devClipBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000054
robertphillipse85a32d2015-02-10 08:16:55 -080055 if (devClipBounds->isEmpty()) {
56 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000057 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000058 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000059
robertphillips@google.com366f1c62012-06-29 21:38:47 +000060 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000061 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000062 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000063 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000064 pathSBounds.roundOut(&pathIBounds);
robertphillipse85a32d2015-02-10 08:16:55 -080065 *devPathBounds = *devClipBounds;
robertphillips@google.com7b112892012-07-31 15:18:21 +000066 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000067 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000068 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000069 return false;
70 }
71 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000072 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000073 return false;
74 }
75 return true;
76}
77
78////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000079void draw_around_inv_path(GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080080 GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -080081 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -080082 const SkMatrix& viewMatrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000083 const SkIRect& devClipBounds,
84 const SkIRect& devPathBounds) {
joshualittd27f73e2014-12-29 07:43:36 -080085 SkMatrix invert;
joshualitt8059eb92014-12-29 15:10:07 -080086 if (!viewMatrix.invert(&invert)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000087 return;
88 }
joshualittd27f73e2014-12-29 07:43:36 -080089
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000090 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000091 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000092 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000093 devClipBounds.fRight, devPathBounds.fTop);
egdaniel8dd688b2015-01-22 10:16:09 -080094 target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000095 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000096 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000097 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000098 devPathBounds.fLeft, devPathBounds.fBottom);
egdaniel8dd688b2015-01-22 10:16:09 -080099 target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000100 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000101 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000102 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000103 devClipBounds.fRight, devPathBounds.fBottom);
egdaniel8dd688b2015-01-22 10:16:09 -0800104 target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000105 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000106 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000107 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000108 devClipBounds.fRight, devClipBounds.fBottom);
egdaniel8dd688b2015-01-22 10:16:09 -0800109 target->drawRect(pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000110 }
111}
112
113}
114
115////////////////////////////////////////////////////////////////////////////////
116// return true on success; false on failure
joshualitt9853cce2014-11-17 14:22:48 -0800117bool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -0800118 GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -0800119 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800120 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800121 const SkPath& path,
robertphillips@google.come79f3202014-02-11 16:30:21 +0000122 const SkStrokeRec& stroke,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000123 bool antiAlias) {
124
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000125 if (NULL == fContext) {
126 return false;
127 }
128
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000129 SkIRect devPathBounds, devClipBounds;
joshualitt44701df2015-02-23 14:44:57 -0800130 if (!get_path_and_clip_bounds(target, pipelineBuilder, path, viewMatrix, &devPathBounds,
131 &devClipBounds)) {
robertphillips@google.come79f3202014-02-11 16:30:21 +0000132 if (path.isInverseFillType()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800133 draw_around_inv_path(target, pipelineBuilder, color, viewMatrix, devClipBounds,
134 devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000135 }
136 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000137 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000138
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000139 SkAutoTUnref<GrTexture> texture(
robertphillips@google.come79f3202014-02-11 16:30:21 +0000140 GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000141 devPathBounds,
joshualitt8059eb92014-12-29 15:10:07 -0800142 antiAlias, &viewMatrix));
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000143 if (NULL == texture) {
144 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000145 }
146
egdaniel8dd688b2015-01-22 10:16:09 -0800147 GrPipelineBuilder copy = *pipelineBuilder;
joshualitt8059eb92014-12-29 15:10:07 -0800148 GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, &copy, color, viewMatrix,
149 devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000150
robertphillips@google.come79f3202014-02-11 16:30:21 +0000151 if (path.isInverseFillType()) {
egdaniel8dd688b2015-01-22 10:16:09 -0800152 draw_around_inv_path(target, pipelineBuilder, color, viewMatrix, devClipBounds,
153 devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000154 }
155
156 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000157}