blob: 13e1c8fb88ef7edbc1248c2ba1bd3140ad01c9ff [file] [log] [blame]
egdaniel87509242014-12-17 13:37:13 -08001/*
2 * Copyright 2014 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrCaps.h"
Greg Danielf91aeb22019-06-18 09:58:02 -04009#include "src/gpu/GrColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrPipeline.h"
11#include "src/gpu/GrProcessor.h"
12#include "src/gpu/GrRenderTargetContext.h"
13#include "src/gpu/effects/GrCoverageSetOpXP.h"
14#include "src/gpu/glsl/GrGLSLBlend.h"
15#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
16#include "src/gpu/glsl/GrGLSLUniformHandler.h"
17#include "src/gpu/glsl/GrGLSLXferProcessor.h"
egdaniel87509242014-12-17 13:37:13 -080018
egdaniel41d4f092015-02-09 07:51:00 -080019class CoverageSetOpXP : public GrXferProcessor {
egdaniel87509242014-12-17 13:37:13 -080020public:
Brian Salomona076d872017-04-04 15:17:03 -040021 CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
Ethan Nicholasabff9562017-10-09 10:54:08 -040022 : INHERITED(kCoverageSetOpXP_ClassID)
23 , fRegionOp(regionOp)
24 , fInvertCoverage(invertCoverage) {}
egdaniel87509242014-12-17 13:37:13 -080025
mtklein36352bf2015-03-25 18:17:31 -070026 const char* name() const override { return "Coverage Set Op"; }
egdaniel41d4f092015-02-09 07:51:00 -080027
egdaniel57d3b032015-11-13 11:57:27 -080028 GrGLSLXferProcessor* createGLSLInstance() const override;
egdaniel41d4f092015-02-09 07:51:00 -080029
egdaniel41d4f092015-02-09 07:51:00 -080030 bool invertCoverage() const { return fInvertCoverage; }
31
32private:
egdaniel41d4f092015-02-09 07:51:00 -080033
Brian Salomon94efbf52016-11-29 13:43:05 -050034 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080035
cdaltonf4f2b442015-04-23 09:40:23 -070036 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
37
mtklein36352bf2015-03-25 18:17:31 -070038 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080039 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
40 return (fRegionOp == xp.fRegionOp &&
41 fInvertCoverage == xp.fInvertCoverage);
42 }
43
44 SkRegion::Op fRegionOp;
45 bool fInvertCoverage;
46
47 typedef GrXferProcessor INHERITED;
48};
49
50///////////////////////////////////////////////////////////////////////////////
51
egdanielfa4cc8b2015-11-13 08:34:52 -080052class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080053public:
54 GLCoverageSetOpXP(const GrProcessor&) {}
55
mtklein36352bf2015-03-25 18:17:31 -070056 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080057
Brian Salomon94efbf52016-11-29 13:43:05 -050058 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080059 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080060 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080061 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
62 b->add32(key);
Mike Kleinfc6c37b2016-09-27 09:34:10 -040063 }
bsalomon50785a32015-02-06 07:02:37 -080064
65private:
cdaltonedbb31f2015-06-08 12:14:44 -070066 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080067 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080068 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080069
70 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080071 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080072 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080073 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080074 }
75 }
76
Mike Kleinfc6c37b2016-09-27 09:34:10 -040077 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
egdaniel87509242014-12-17 13:37:13 -080078
egdanielfa4cc8b2015-11-13 08:34:52 -080079 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080080};
81
82///////////////////////////////////////////////////////////////////////////////
83
Brian Salomon94efbf52016-11-29 13:43:05 -050084void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080085 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -080086 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -080087}
88
egdaniel57d3b032015-11-13 11:57:27 -080089GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -070090 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -080091}
92
cdaltonf4f2b442015-04-23 09:40:23 -070093void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -080094 switch (fRegionOp) {
95 case SkRegion::kReplace_Op:
96 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
97 blendInfo->fDstBlend = kZero_GrBlendCoeff;
98 break;
99 case SkRegion::kIntersect_Op:
100 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
101 blendInfo->fDstBlend = kZero_GrBlendCoeff;
102 break;
103 case SkRegion::kUnion_Op:
104 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
105 blendInfo->fDstBlend = kISC_GrBlendCoeff;
106 break;
107 case SkRegion::kXOR_Op:
108 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
109 blendInfo->fDstBlend = kISC_GrBlendCoeff;
110 break;
111 case SkRegion::kDifference_Op:
112 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
113 blendInfo->fDstBlend = kISC_GrBlendCoeff;
114 break;
115 case SkRegion::kReverseDifference_Op:
116 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
117 blendInfo->fDstBlend = kZero_GrBlendCoeff;
118 break;
119 }
Brian Osman422f95b2018-11-05 16:49:04 -0500120 blendInfo->fBlendConstant = SK_PMColor4fTRANSPARENT;
egdaniel87509242014-12-17 13:37:13 -0800121}
122
123///////////////////////////////////////////////////////////////////////////////
124
Brian Salomona1633922017-01-09 11:46:10 -0500125constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
126 bool invertCoverage)
127 : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
egdaniel87509242014-12-17 13:37:13 -0800128
Brian Salomona1633922017-01-09 11:46:10 -0500129const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
130 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
131 // null.
132#ifdef SK_BUILD_FOR_WIN
133#define _CONSTEXPR_
134#else
135#define _CONSTEXPR_ constexpr
136#endif
egdaniel87509242014-12-17 13:37:13 -0800137 switch (regionOp) {
138 case SkRegion::kReplace_Op: {
139 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500140 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
141 SkRegion::kReplace_Op, true);
142 return &gReplaceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800143 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500144 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
145 SkRegion::kReplace_Op, false);
146 return &gReplaceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800147 }
egdaniel87509242014-12-17 13:37:13 -0800148 }
149 case SkRegion::kIntersect_Op: {
150 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500151 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
152 SkRegion::kIntersect_Op, true);
153 return &gIntersectCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800154 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500155 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
156 SkRegion::kIntersect_Op, false);
157 return &gIntersectCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800158 }
egdaniel87509242014-12-17 13:37:13 -0800159 }
160 case SkRegion::kUnion_Op: {
161 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500162 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
163 true);
164 return &gUnionCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800165 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500166 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
167 false);
168 return &gUnionCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800169 }
egdaniel87509242014-12-17 13:37:13 -0800170 }
171 case SkRegion::kXOR_Op: {
172 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500173 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
174 true);
175 return &gXORCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800176 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500177 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
178 false);
179 return &gXORCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800180 }
egdaniel87509242014-12-17 13:37:13 -0800181 }
182 case SkRegion::kDifference_Op: {
183 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500184 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
185 SkRegion::kDifference_Op, true);
186 return &gDifferenceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800187 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500188 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
189 SkRegion::kDifference_Op, false);
190 return &gDifferenceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800191 }
egdaniel87509242014-12-17 13:37:13 -0800192 }
193 case SkRegion::kReverseDifference_Op: {
194 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500195 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
196 SkRegion::kReverseDifference_Op, true);
197 return &gRevDiffCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800198 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500199 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
200 SkRegion::kReverseDifference_Op, false);
201 return &gRevDiffCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800202 }
egdaniel87509242014-12-17 13:37:13 -0800203 }
egdaniel87509242014-12-17 13:37:13 -0800204 }
Brian Salomona1633922017-01-09 11:46:10 -0500205#undef _CONSTEXPR_
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400206 SK_ABORT("Unknown region op.");
Brian Salomona1633922017-01-09 11:46:10 -0500207 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800208}
209
Brian Salomond61c9d92017-04-10 10:54:25 -0400210sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor(
211 const GrProcessorAnalysisColor&,
212 GrProcessorAnalysisCoverage,
213 bool hasMixedSamples,
Brian Osman5ced0bf2019-03-15 10:15:29 -0400214 const GrCaps& caps,
215 GrClampType) const {
cdalton86ae0a92015-06-08 15:11:04 -0700216 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
217 // the future, however we could at some point make this work using an inverted coverage
218 // modulation table. Note that an inverted table still won't work if there are coverage procs.
219 if (fInvertCoverage && hasMixedSamples) {
220 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700221 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700222 }
223
Brian Salomona076d872017-04-04 15:17:03 -0400224 return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage));
egdaniel87509242014-12-17 13:37:13 -0800225}
226
egdaniel87509242014-12-17 13:37:13 -0800227GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
228
Hal Canary6f6961e2017-01-31 13:50:44 -0500229#if GR_TEST_UTILS
Brian Salomona1633922017-01-09 11:46:10 -0500230const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700231 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
Brian Salomon7c8460e2017-05-12 11:36:10 -0400232 bool isMixedSamples = GrFSAAType::kMixedSamples == d->fRenderTargetContext->fsaaType();
233 bool invertCoverage = !isMixedSamples && d->fRandom->nextBool();
Brian Salomon0721fe92017-04-04 19:04:00 -0400234 return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800235}
Hal Canary6f6961e2017-01-31 13:50:44 -0500236#endif