blob: ca2ca64db8bb85b09b40447c24e404319c7943f3 [file] [log] [blame]
robertphillips@google.comf4c2c522012-04-27 12:08:47 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrSoftwarePathRenderer.h"
robertphillips@google.comed4155d2012-05-01 14:30:24 +00009#include "GrContext.h"
robertphillips@google.com58b20212012-06-27 20:44:52 +000010#include "GrSWMaskHelper.h"
joshualitt04194f32016-01-13 10:08:27 -080011#include "batches/GrRectBatchFactory.h"
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000012
robertphillips@google.comed4155d2012-05-01 14:30:24 +000013////////////////////////////////////////////////////////////////////////////////
bsalomon0aff2fa2015-07-31 06:48:27 -070014bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
halcanary96fcdcc2015-08-27 07:41:13 -070015 if (nullptr == fContext) {
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000016 return false;
17 }
bsalomon0aff2fa2015-07-31 06:48:27 -070018 if (args.fStroke->isDashed()) {
kkinnunen18996512015-04-26 23:18:49 -070019 return false;
20 }
robertphillips@google.comed4155d2012-05-01 14:30:24 +000021 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000022}
23
robertphillips@google.comed4155d2012-05-01 14:30:24 +000024namespace {
25
26////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000027// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000028// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000029// path bounds would be empty.
robertphillipsb83bec52015-10-23 09:38:03 -070030bool get_path_and_clip_bounds(const GrPipelineBuilder* pipelineBuilder,
robertphillips@google.comed4155d2012-05-01 14:30:24 +000031 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000032 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000033 SkIRect* devPathBounds,
34 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000035 // compute bounds as intersection of rt size, clip, and path
egdaniel8dd688b2015-01-22 10:16:09 -080036 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -070037 if (nullptr == rt) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000038 return false;
39 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000040
robertphillips7bceedc2015-12-01 12:51:26 -080041 pipelineBuilder->clip().getConservativeBounds(rt->width(), rt->height(), devClipBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000042
robertphillipse85a32d2015-02-10 08:16:55 -080043 if (devClipBounds->isEmpty()) {
44 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000045 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000046 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000047
robertphillips@google.com366f1c62012-06-29 21:38:47 +000048 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000049 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000050 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000051 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000052 pathSBounds.roundOut(&pathIBounds);
robertphillipse85a32d2015-02-10 08:16:55 -080053 *devPathBounds = *devClipBounds;
robertphillips@google.com7b112892012-07-31 15:18:21 +000054 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000055 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000056 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000057 return false;
58 }
59 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000060 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000061 return false;
62 }
63 return true;
64}
65
66////////////////////////////////////////////////////////////////////////////////
joshualitt04194f32016-01-13 10:08:27 -080067static void draw_non_aa_rect(GrDrawTarget* drawTarget,
68 const GrPipelineBuilder& pipelineBuilder,
69 GrColor color,
70 const SkMatrix& viewMatrix,
71 const SkRect& rect,
72 const SkMatrix& localMatrix) {
73 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
74 nullptr, &localMatrix));
75 drawTarget->drawBatch(pipelineBuilder, batch);
76}
77
robertphillips@google.comed4155d2012-05-01 14:30:24 +000078void draw_around_inv_path(GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080079 GrPipelineBuilder* pipelineBuilder,
joshualitt2e3b3e32014-12-09 13:31:14 -080080 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -080081 const SkMatrix& viewMatrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000082 const SkIRect& devClipBounds,
83 const SkIRect& devPathBounds) {
joshualittd27f73e2014-12-29 07:43:36 -080084 SkMatrix invert;
joshualitt8059eb92014-12-29 15:10:07 -080085 if (!viewMatrix.invert(&invert)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000086 return;
87 }
joshualittd27f73e2014-12-29 07:43:36 -080088
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000089 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000090 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000091 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000092 devClipBounds.fRight, devPathBounds.fTop);
joshualitt04194f32016-01-13 10:08:27 -080093 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000094 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000095 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000096 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000097 devPathBounds.fLeft, devPathBounds.fBottom);
joshualitt04194f32016-01-13 10:08:27 -080098 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000099 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000100 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000101 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000102 devClipBounds.fRight, devPathBounds.fBottom);
joshualitt04194f32016-01-13 10:08:27 -0800103 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000104 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000105 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000106 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000107 devClipBounds.fRight, devClipBounds.fBottom);
joshualitt04194f32016-01-13 10:08:27 -0800108 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000109 }
110}
111
112}
113
114////////////////////////////////////////////////////////////////////////////////
115// return true on success; false on failure
bsalomon0aff2fa2015-07-31 06:48:27 -0700116bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
joshualittde83b412016-01-14 09:58:36 -0800117 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrSoftwarePathRenderer::onDrawPath");
halcanary96fcdcc2015-08-27 07:41:13 -0700118 if (nullptr == fContext) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000119 return false;
120 }
121
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000122 SkIRect devPathBounds, devClipBounds;
robertphillipsb83bec52015-10-23 09:38:03 -0700123 if (!get_path_and_clip_bounds(args.fPipelineBuilder, *args.fPath,
bsalomon0aff2fa2015-07-31 06:48:27 -0700124 *args.fViewMatrix, &devPathBounds, &devClipBounds)) {
125 if (args.fPath->isInverseFillType()) {
126 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor,
127 *args.fViewMatrix, devClipBounds, devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000128 }
129 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000130 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000131
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000132 SkAutoTUnref<GrTexture> texture(
bsalomon0aff2fa2015-07-31 06:48:27 -0700133 GrSWMaskHelper::DrawPathMaskToTexture(fContext, *args.fPath, *args.fStroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000134 devPathBounds,
bsalomon0aff2fa2015-07-31 06:48:27 -0700135 args.fAntiAlias, args.fViewMatrix));
halcanary96fcdcc2015-08-27 07:41:13 -0700136 if (nullptr == texture) {
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000137 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000138 }
139
bsalomon0aff2fa2015-07-31 06:48:27 -0700140 GrSWMaskHelper::DrawToTargetWithPathMask(texture, args.fTarget, args.fPipelineBuilder,
141 args.fColor, *args.fViewMatrix, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000142
bsalomon0aff2fa2015-07-31 06:48:27 -0700143 if (args.fPath->isInverseFillType()) {
144 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor, *args.fViewMatrix,
145 devClipBounds, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000146 }
147
148 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000149}