blob: aefaf27308e0b51d25501c66d1073512c6d503dc [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.com58b20212012-06-27 20:44:52 +00009#include "GrSWMaskHelper.h"
robertphillips0152d732016-05-20 06:38:43 -070010#include "GrTextureProvider.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 {
robertphillips0152d732016-05-20 06:38:43 -070015 return SkToBool(fTexProvider);
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000016}
17
robertphillips@google.comed4155d2012-05-01 14:30:24 +000018namespace {
19
20////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000021// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000022// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000023// path bounds would be empty.
robertphillips0152d732016-05-20 06:38:43 -070024bool get_path_and_clip_bounds(int width, int height,
cdalton862cff32016-05-12 15:09:48 -070025 const GrClip& clip,
robertphillips@google.comed4155d2012-05-01 14:30:24 +000026 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000027 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000028 SkIRect* devPathBounds,
29 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000030 // compute bounds as intersection of rt size, clip, and path
robertphillips0152d732016-05-20 06:38:43 -070031 clip.getConservativeBounds(width, height, devClipBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000032
robertphillipse85a32d2015-02-10 08:16:55 -080033 if (devClipBounds->isEmpty()) {
robertphillips0152d732016-05-20 06:38:43 -070034 *devPathBounds = SkIRect::MakeWH(width, height);
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000035 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000036 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000037
robertphillips@google.com366f1c62012-06-29 21:38:47 +000038 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000039 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000040 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000041 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000042 pathSBounds.roundOut(&pathIBounds);
robertphillipse85a32d2015-02-10 08:16:55 -080043 *devPathBounds = *devClipBounds;
robertphillips@google.com7b112892012-07-31 15:18:21 +000044 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000045 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000046 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000047 return false;
48 }
49 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000050 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000051 return false;
52 }
53 return true;
54}
55
56////////////////////////////////////////////////////////////////////////////////
joshualitt04194f32016-01-13 10:08:27 -080057static void draw_non_aa_rect(GrDrawTarget* drawTarget,
58 const GrPipelineBuilder& pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -070059 const GrClip& clip,
joshualitt04194f32016-01-13 10:08:27 -080060 GrColor color,
61 const SkMatrix& viewMatrix,
62 const SkRect& rect,
63 const SkMatrix& localMatrix) {
64 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
65 nullptr, &localMatrix));
cdalton862cff32016-05-12 15:09:48 -070066 drawTarget->drawBatch(pipelineBuilder, clip, batch);
joshualitt04194f32016-01-13 10:08:27 -080067}
68
robertphillips@google.comed4155d2012-05-01 14:30:24 +000069void draw_around_inv_path(GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -080070 GrPipelineBuilder* pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -070071 const GrClip& clip,
joshualitt2e3b3e32014-12-09 13:31:14 -080072 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -080073 const SkMatrix& viewMatrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000074 const SkIRect& devClipBounds,
75 const SkIRect& devPathBounds) {
joshualittd27f73e2014-12-29 07:43:36 -080076 SkMatrix invert;
joshualitt8059eb92014-12-29 15:10:07 -080077 if (!viewMatrix.invert(&invert)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000078 return;
79 }
joshualittd27f73e2014-12-29 07:43:36 -080080
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000081 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000082 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000083 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000084 devClipBounds.fRight, devPathBounds.fTop);
cdalton862cff32016-05-12 15:09:48 -070085 draw_non_aa_rect(target, *pipelineBuilder, clip, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000086 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000087 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000088 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000089 devPathBounds.fLeft, devPathBounds.fBottom);
cdalton862cff32016-05-12 15:09:48 -070090 draw_non_aa_rect(target, *pipelineBuilder, clip, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000091 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000092 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000093 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000094 devClipBounds.fRight, devPathBounds.fBottom);
cdalton862cff32016-05-12 15:09:48 -070095 draw_non_aa_rect(target, *pipelineBuilder, clip, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000096 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000097 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000098 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +000099 devClipBounds.fRight, devClipBounds.fBottom);
cdalton862cff32016-05-12 15:09:48 -0700100 draw_non_aa_rect(target, *pipelineBuilder, clip, color, SkMatrix::I(), rect, invert);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000101 }
102}
103
104}
105
106////////////////////////////////////////////////////////////////////////////////
107// return true on success; false on failure
bsalomon0aff2fa2015-07-31 06:48:27 -0700108bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
joshualittde83b412016-01-14 09:58:36 -0800109 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrSoftwarePathRenderer::onDrawPath");
robertphillips0152d732016-05-20 06:38:43 -0700110 if (!fTexProvider || !args.fPipelineBuilder->getRenderTarget()) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000111 return false;
112 }
113
robertphillips0152d732016-05-20 06:38:43 -0700114 const int width = args.fPipelineBuilder->getRenderTarget()->width();
115 const int height = args.fPipelineBuilder->getRenderTarget()->height();
116
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000117 SkIRect devPathBounds, devClipBounds;
robertphillips0152d732016-05-20 06:38:43 -0700118 if (!get_path_and_clip_bounds(width, height, *args.fClip, *args.fPath,
bsalomon0aff2fa2015-07-31 06:48:27 -0700119 *args.fViewMatrix, &devPathBounds, &devClipBounds)) {
120 if (args.fPath->isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -0700121 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, *args.fClip, args.fColor,
bsalomon0aff2fa2015-07-31 06:48:27 -0700122 *args.fViewMatrix, devClipBounds, devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000123 }
124 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000125 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000126
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000127 SkAutoTUnref<GrTexture> texture(
robertphillips0152d732016-05-20 06:38:43 -0700128 GrSWMaskHelper::DrawPathMaskToTexture(fTexProvider, *args.fPath, *args.fStyle,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000129 devPathBounds,
bsalomon0aff2fa2015-07-31 06:48:27 -0700130 args.fAntiAlias, args.fViewMatrix));
halcanary96fcdcc2015-08-27 07:41:13 -0700131 if (nullptr == texture) {
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000132 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000133 }
134
bsalomon0aff2fa2015-07-31 06:48:27 -0700135 GrSWMaskHelper::DrawToTargetWithPathMask(texture, args.fTarget, args.fPipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700136 *args.fClip, args.fColor, *args.fViewMatrix,
137 devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000138
bsalomon0aff2fa2015-07-31 06:48:27 -0700139 if (args.fPath->isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -0700140 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, *args.fClip, args.fColor,
141 *args.fViewMatrix, devClipBounds, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000142 }
143
144 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000145}