blob: b6bf9408248503f8f785d91d21d8886a73d5ef27 [file] [log] [blame]
bsalomon@google.comded4f4b2012-06-28 18:48:06 +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
9#include "GrStencilAndCoverPathRenderer.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070010#include "GrCaps.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000011#include "GrContext.h"
Brian Osman11052242016-10-27 14:47:55 -040012#include "GrRenderTargetContextPriv.h"
cdalton8ff8d242015-12-08 10:20:32 -080013#include "GrDrawPathBatch.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070014#include "GrFixedClip.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070015#include "GrGpu.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000016#include "GrPath.h"
bsalomonbb243832016-07-22 07:10:19 -070017#include "GrPipelineBuilder.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080018#include "GrRenderTarget.h"
bsalomond309e7a2015-04-30 14:18:54 -070019#include "GrResourceProvider.h"
robertphillips976f5f02016-06-03 10:59:20 -070020#include "GrStencilPathBatch.h"
bsalomon6663acf2016-05-10 09:14:17 -070021#include "GrStyle.h"
joshualitt04194f32016-01-13 10:08:27 -080022#include "batches/GrRectBatchFactory.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000023
bsalomon706f08f2015-05-22 07:35:58 -070024GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider,
25 const GrCaps& caps) {
26 if (caps.shaderCaps()->pathRenderingSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -070027 return new GrStencilAndCoverPathRenderer(resourceProvider);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000028 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070029 return nullptr;
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000030 }
31}
32
bsalomon706f08f2015-05-22 07:35:58 -070033GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider* resourceProvider)
halcanary9d524f22016-03-29 09:03:52 -070034 : fResourceProvider(resourceProvider) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000035}
36
bsalomon0aff2fa2015-07-31 06:48:27 -070037bool GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
bsalomonee432412016-06-27 07:18:18 -070038 // GrPath doesn't support hairline paths. An arbitrary path effect could produce a hairline
39 // path.
40 if (args.fShape->style().strokeRec().isHairlineStyle() ||
41 args.fShape->style().hasNonDashPathEffect()) {
vbuzinovdded6962015-06-12 08:59:45 -070042 return false;
43 }
cdalton93a379b2016-05-11 13:58:08 -070044 if (args.fHasUserStencilSettings) {
vbuzinovdded6962015-06-12 08:59:45 -070045 return false;
46 }
bsalomon0aff2fa2015-07-31 06:48:27 -070047 if (args.fAntiAlias) {
robertphillips68737822015-10-29 12:12:21 -070048 return args.fIsStencilBufferMSAA;
vbuzinovdded6962015-06-12 08:59:45 -070049 } else {
50 return true; // doesn't do per-path AA, relies on the target having MSAA
51 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000052}
53
bsalomon7bffcd22016-09-15 13:55:33 -070054static GrPath* get_gr_path(GrResourceProvider* resourceProvider, const GrShape& shape) {
bsalomon8718aaf2015-02-19 07:24:21 -080055 GrUniqueKey key;
kkinnunen070e0102015-05-21 00:37:30 -070056 bool isVolatile;
bsalomon7bffcd22016-09-15 13:55:33 -070057 GrPath::ComputeKey(shape, &key, &isVolatile);
58 sk_sp<GrPath> path;
59 if (!isVolatile) {
60 path.reset(
61 static_cast<GrPath*>(resourceProvider->findAndRefResourceByUniqueKey(key)));
62 }
bsalomon706f08f2015-05-22 07:35:58 -070063 if (!path) {
bsalomon7bffcd22016-09-15 13:55:33 -070064 SkPath skPath;
65 shape.asPath(&skPath);
66 path.reset(resourceProvider->createPath(skPath, shape.style()));
kkinnunen070e0102015-05-21 00:37:30 -070067 if (!isVolatile) {
bsalomon7bffcd22016-09-15 13:55:33 -070068 resourceProvider->assignUniqueKeyToResource(key, path.get());
kkinnunen070e0102015-05-21 00:37:30 -070069 }
kkinnunen50b58e62015-05-18 23:02:07 -070070 } else {
bsalomon7bffcd22016-09-15 13:55:33 -070071#ifdef SK_DEBUG
72 SkPath skPath;
73 shape.asPath(&skPath);
74 SkASSERT(path->isEqualTo(skPath, shape.style()));
75#endif
cdalton4e205b12014-09-17 09:41:24 -070076 }
mtklein18300a32016-03-16 13:53:35 -070077 return path.release();
cdalton4e205b12014-09-17 09:41:24 -070078}
79
bsalomon0aff2fa2015-07-31 06:48:27 -070080void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -040081 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -080082 "GrStencilAndCoverPathRenderer::onStencilPath");
Brian Osman11052242016-10-27 14:47:55 -040083 SkASSERT(!args.fIsAA || args.fRenderTargetContext->isStencilBufferMultisampled());
robertphillips976f5f02016-06-03 10:59:20 -070084
bsalomon7bffcd22016-09-15 13:55:33 -070085 SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, *args.fShape));
Brian Osman693a5402016-10-27 15:13:22 -040086 args.fRenderTargetContext->priv().stencilPath(*args.fClip, args.fIsAA, *args.fViewMatrix, p);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000087}
88
bsalomon0aff2fa2015-07-31 06:48:27 -070089bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -040090 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -080091 "GrStencilAndCoverPathRenderer::onDrawPath");
Brian Osman11052242016-10-27 14:47:55 -040092 SkASSERT(!args.fPaint->isAntiAlias() ||
93 args.fRenderTargetContext->isStencilBufferMultisampled());
bsalomon8acedde2016-06-24 10:42:16 -070094 SkASSERT(!args.fShape->style().strokeRec().isHairlineStyle());
95
bsalomon0aff2fa2015-07-31 06:48:27 -070096 const SkMatrix& viewMatrix = *args.fViewMatrix;
97
bsalomon8acedde2016-06-24 10:42:16 -070098
bsalomona224bb72016-10-03 09:48:22 -070099 SkAutoTUnref<GrPath> path(get_gr_path(fResourceProvider, *args.fShape));
bsalomon@google.com0f11e1a2012-10-08 14:48:36 +0000100
bsalomona224bb72016-10-03 09:48:22 -0700101 if (args.fShape->inverseFilled()) {
joshualittd27f73e2014-12-29 07:43:36 -0800102 SkMatrix invert = SkMatrix::I();
egdaniel8dd688b2015-01-22 10:16:09 -0800103 SkRect bounds =
robertphillips976f5f02016-06-03 10:59:20 -0700104 SkRect::MakeLTRB(0, 0,
Brian Osman11052242016-10-27 14:47:55 -0400105 SkIntToScalar(args.fRenderTargetContext->width()),
106 SkIntToScalar(args.fRenderTargetContext->height()));
joshualitt92e496f2014-10-31 13:56:50 -0700107 SkMatrix vmi;
108 // mapRect through persp matrix may not be correct
joshualitt8059eb92014-12-29 15:10:07 -0800109 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
joshualitt92e496f2014-10-31 13:56:50 -0700110 vmi.mapRect(&bounds);
111 // theoretically could set bloat = 0, instead leave it because of matrix inversion
112 // precision.
joshualitt8059eb92014-12-29 15:10:07 -0800113 SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf;
joshualitt92e496f2014-10-31 13:56:50 -0700114 bounds.outset(bloat, bloat);
115 } else {
joshualitt8059eb92014-12-29 15:10:07 -0800116 if (!viewMatrix.invert(&invert)) {
joshualittd27f73e2014-12-29 07:43:36 -0800117 return false;
118 }
joshualitt92e496f2014-10-31 13:56:50 -0700119 }
joshualitt8059eb92014-12-29 15:10:07 -0800120 const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : viewMatrix;
joshualitt04194f32016-01-13 10:08:27 -0800121
csmartdaltonecbc12b2016-06-08 10:08:43 -0700122 SkAutoTUnref<GrDrawBatch> coverBatch(
robertphillips3950f0d2016-07-07 07:33:13 -0700123 GrRectBatchFactory::CreateNonAAFill(args.fPaint->getColor(), viewM, bounds,
124 nullptr, &invert));
robertphillips976f5f02016-06-03 10:59:20 -0700125
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700126 // fake inverse with a stencil and cover
Brian Osman693a5402016-10-27 15:13:22 -0400127 args.fRenderTargetContext->priv().stencilPath(*args.fClip, args.fPaint->isAntiAlias(),
128 viewMatrix, path);
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700129
bsalomonbb243832016-07-22 07:10:19 -0700130 {
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700131 static constexpr GrUserStencilSettings kInvertedCoverPass(
132 GrUserStencilSettings::StaticInit<
133 0x0000,
134 // We know our rect will hit pixels outside the clip and the user bits will
135 // be 0 outside the clip. So we can't just fill where the user bits are 0. We
136 // also need to check that the clip bit is set.
137 GrUserStencilTest::kEqualIfInClip,
138 0xffff,
139 GrUserStencilOp::kKeep,
140 GrUserStencilOp::kZero,
141 0xffff>()
142 );
143
bsalomonbb243832016-07-22 07:10:19 -0700144 GrPipelineBuilder pipelineBuilder(*args.fPaint,
145 args.fPaint->isAntiAlias() &&
Brian Osman11052242016-10-27 14:47:55 -0400146 !args.fRenderTargetContext->hasMixedSamples());
bsalomonbb243832016-07-22 07:10:19 -0700147 pipelineBuilder.setUserStencil(&kInvertedCoverPass);
148
Brian Osman11052242016-10-27 14:47:55 -0400149 args.fRenderTargetContext->drawBatch(pipelineBuilder, *args.fClip, coverBatch);
bsalomonbb243832016-07-22 07:10:19 -0700150 }
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000151 } else {
cdalton93a379b2016-05-11 13:58:08 -0700152 static constexpr GrUserStencilSettings kCoverPass(
153 GrUserStencilSettings::StaticInit<
154 0x0000,
155 GrUserStencilTest::kNotEqual,
156 0xffff,
157 GrUserStencilOp::kZero,
158 GrUserStencilOp::kKeep,
159 0xffff>()
160 );
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000161
bsalomona224bb72016-10-03 09:48:22 -0700162 SkAutoTUnref<GrDrawBatch> batch(GrDrawPathBatch::Create(viewMatrix, args.fPaint->getColor(),
163 path));
robertphillips976f5f02016-06-03 10:59:20 -0700164
bsalomonbb243832016-07-22 07:10:19 -0700165 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fPaint->isAntiAlias());
166 pipelineBuilder.setUserStencil(&kCoverPass);
167 if (args.fAntiAlias) {
Brian Osman11052242016-10-27 14:47:55 -0400168 SkASSERT(args.fRenderTargetContext->isStencilBufferMultisampled());
bsalomonbb243832016-07-22 07:10:19 -0700169 pipelineBuilder.enableState(GrPipelineBuilder::kHWAntialias_Flag);
170 }
171
Brian Osman11052242016-10-27 14:47:55 -0400172 args.fRenderTargetContext->drawBatch(pipelineBuilder, *args.fClip, batch);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000173 }
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000174
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000175 return true;
176}