blob: 401246ea5c6f7e0c3afb1f3298124d2d46a5061e [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"
bsalomon72e3ae42015-04-28 08:08:46 -070012#include "GrVertexBuffer.h"
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000013
robertphillips@google.comed4155d2012-05-01 14:30:24 +000014////////////////////////////////////////////////////////////////////////////////
bsalomon0aff2fa2015-07-31 06:48:27 -070015bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
robertphillips730c0442014-07-25 05:52:38 -070016 if (NULL == fContext) {
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000017 return false;
18 }
bsalomon0aff2fa2015-07-31 06:48:27 -070019 if (args.fStroke->isDashed()) {
kkinnunen18996512015-04-26 23:18:49 -070020 return false;
21 }
robertphillips@google.comed4155d2012-05-01 14:30:24 +000022 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000023}
24
joshualitt9853cce2014-11-17 14:22:48 -080025GrPathRenderer::StencilSupport
26GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
egdaniel8dd688b2015-01-22 10:16:09 -080027 const GrPipelineBuilder*,
joshualitt9853cce2014-11-17 14:22:48 -080028 const SkPath&,
kkinnunen18996512015-04-26 23:18:49 -070029 const GrStrokeInfo&) const {
bsalomon@google.com45a15f52012-12-10 19:10:17 +000030 return GrPathRenderer::kNoSupport_StencilSupport;
31}
32
robertphillips@google.comed4155d2012-05-01 14:30:24 +000033namespace {
34
35////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000036// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000037// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000038// path bounds would be empty.
39bool get_path_and_clip_bounds(const GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080040 const GrPipelineBuilder* pipelineBuilder,
robertphillips@google.comed4155d2012-05-01 14:30:24 +000041 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000042 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000043 SkIRect* devPathBounds,
44 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000045 // compute bounds as intersection of rt size, clip, and path
egdaniel8dd688b2015-01-22 10:16:09 -080046 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000047 if (NULL == rt) {
48 return false;
49 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000050
joshualitt44701df2015-02-23 14:44:57 -080051 pipelineBuilder->clip().getConservativeBounds(rt, devClipBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000052
robertphillipse85a32d2015-02-10 08:16:55 -080053 if (devClipBounds->isEmpty()) {
54 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000055 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000056 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000057
robertphillips@google.com366f1c62012-06-29 21:38:47 +000058 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000059 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000060 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000061 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000062 pathSBounds.roundOut(&pathIBounds);
robertphillipse85a32d2015-02-10 08:16:55 -080063 *devPathBounds = *devClipBounds;
robertphillips@google.com7b112892012-07-31 15:18:21 +000064 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000065 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000066 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000067 return false;
68 }
69 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000070 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000071 return false;
72 }
73 return true;
74}
75
76////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000077void draw_around_inv_path(GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080078 GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -080079 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -080080 const SkMatrix& viewMatrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000081 const SkIRect& devClipBounds,
82 const SkIRect& devPathBounds) {
joshualittd27f73e2014-12-29 07:43:36 -080083 SkMatrix invert;
joshualitt8059eb92014-12-29 15:10:07 -080084 if (!viewMatrix.invert(&invert)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000085 return;
86 }
joshualittd27f73e2014-12-29 07:43:36 -080087
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000088 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000089 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000090 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000091 devClipBounds.fRight, devPathBounds.fTop);
joshualitt1c735482015-07-13 08:08:25 -070092 target->drawBWRect(*pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000093 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000094 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000095 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000096 devPathBounds.fLeft, devPathBounds.fBottom);
joshualitt1c735482015-07-13 08:08:25 -070097 target->drawBWRect(*pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000098 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000099 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000100 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000101 devClipBounds.fRight, devPathBounds.fBottom);
joshualitt1c735482015-07-13 08:08:25 -0700102 target->drawBWRect(*pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000103 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000104 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000105 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000106 devClipBounds.fRight, devClipBounds.fBottom);
joshualitt1c735482015-07-13 08:08:25 -0700107 target->drawBWRect(*pipelineBuilder, color, SkMatrix::I(), rect, NULL, &invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000108 }
109}
110
111}
112
113////////////////////////////////////////////////////////////////////////////////
114// return true on success; false on failure
bsalomon0aff2fa2015-07-31 06:48:27 -0700115bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000116 if (NULL == fContext) {
117 return false;
118 }
119
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000120 SkIRect devPathBounds, devClipBounds;
bsalomon0aff2fa2015-07-31 06:48:27 -0700121 if (!get_path_and_clip_bounds(args.fTarget, args.fPipelineBuilder, *args.fPath,
122 *args.fViewMatrix, &devPathBounds, &devClipBounds)) {
123 if (args.fPath->isInverseFillType()) {
124 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor,
125 *args.fViewMatrix, devClipBounds, devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000126 }
127 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000128 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000129
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000130 SkAutoTUnref<GrTexture> texture(
bsalomon0aff2fa2015-07-31 06:48:27 -0700131 GrSWMaskHelper::DrawPathMaskToTexture(fContext, *args.fPath, *args.fStroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000132 devPathBounds,
bsalomon0aff2fa2015-07-31 06:48:27 -0700133 args.fAntiAlias, args.fViewMatrix));
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000134 if (NULL == texture) {
135 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000136 }
137
bsalomon0aff2fa2015-07-31 06:48:27 -0700138 GrSWMaskHelper::DrawToTargetWithPathMask(texture, args.fTarget, args.fPipelineBuilder,
139 args.fColor, *args.fViewMatrix, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000140
bsalomon0aff2fa2015-07-31 06:48:27 -0700141 if (args.fPath->isInverseFillType()) {
142 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor, *args.fViewMatrix,
143 devClipBounds, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000144 }
145
146 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000147}