blob: 10137068429acbb32bc8c8778a4166974bd1741b [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
8#include "effects/GrCoverageSetOpXP.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -07009#include "GrCaps.h"
egdaniel87509242014-12-17 13:37:13 -080010#include "GrColor.h"
ethannicholas22793252016-01-30 09:59:10 -080011#include "GrPipeline.h"
egdaniel87509242014-12-17 13:37:13 -080012#include "GrProcessor.h"
Brian Salomonc0b642c2017-03-27 13:09:36 -040013#include "GrRenderTargetContext.h"
egdanielf34b2932015-12-01 13:54:06 -080014#include "glsl/GrGLSLBlend.h"
egdaniel2d721d32015-11-11 13:06:05 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel7ea439b2015-12-03 09:20:44 -080016#include "glsl/GrGLSLUniformHandler.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080017#include "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:
egdaniel41d4f092015-02-09 07:51:00 -080021 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
halcanary385fe4d2015-08-26 13:07:48 -070022 return new CoverageSetOpXP(regionOp, invertCoverage);
egdaniel41d4f092015-02-09 07:51:00 -080023 }
egdaniel87509242014-12-17 13:37:13 -080024
mtklein36352bf2015-03-25 18:17:31 -070025 ~CoverageSetOpXP() override;
egdaniel41d4f092015-02-09 07:51:00 -080026
mtklein36352bf2015-03-25 18:17:31 -070027 const char* name() const override { return "Coverage Set Op"; }
egdaniel41d4f092015-02-09 07:51:00 -080028
egdaniel57d3b032015-11-13 11:57:27 -080029 GrGLSLXferProcessor* createGLSLInstance() const override;
egdaniel41d4f092015-02-09 07:51:00 -080030
egdaniel41d4f092015-02-09 07:51:00 -080031 bool invertCoverage() const { return fInvertCoverage; }
32
33private:
34 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
35
Brian Salomon1c10fdd2017-03-03 14:30:15 -050036 GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
egdanielc19cdc22015-05-10 08:45:18 -070037
Brian Salomon94efbf52016-11-29 13:43:05 -050038 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080039
cdaltonf4f2b442015-04-23 09:40:23 -070040 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
41
mtklein36352bf2015-03-25 18:17:31 -070042 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080043 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
44 return (fRegionOp == xp.fRegionOp &&
45 fInvertCoverage == xp.fInvertCoverage);
46 }
47
48 SkRegion::Op fRegionOp;
49 bool fInvertCoverage;
50
51 typedef GrXferProcessor INHERITED;
52};
53
54///////////////////////////////////////////////////////////////////////////////
55
egdanielfa4cc8b2015-11-13 08:34:52 -080056class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080057public:
58 GLCoverageSetOpXP(const GrProcessor&) {}
59
mtklein36352bf2015-03-25 18:17:31 -070060 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080061
Brian Salomon94efbf52016-11-29 13:43:05 -050062 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080063 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080064 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080065 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
66 b->add32(key);
Mike Kleinfc6c37b2016-09-27 09:34:10 -040067 }
bsalomon50785a32015-02-06 07:02:37 -080068
69private:
cdaltonedbb31f2015-06-08 12:14:44 -070070 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080071 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080072 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080073
74 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080075 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080076 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080077 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080078 }
79 }
80
Mike Kleinfc6c37b2016-09-27 09:34:10 -040081 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
egdaniel87509242014-12-17 13:37:13 -080082
egdanielfa4cc8b2015-11-13 08:34:52 -080083 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080084};
85
86///////////////////////////////////////////////////////////////////////////////
87
egdaniel41d4f092015-02-09 07:51:00 -080088CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080089 : fRegionOp(regionOp)
90 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080091 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080092}
93
egdaniel41d4f092015-02-09 07:51:00 -080094CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080095}
96
Brian Salomon94efbf52016-11-29 13:43:05 -050097void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080098 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -080099 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800100}
101
egdaniel57d3b032015-11-13 11:57:27 -0800102GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700103 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800104}
105
Brian Salomon5298dc82017-02-22 11:52:03 -0500106GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(
Brian Salomon1c10fdd2017-03-03 14:30:15 -0500107 const FragmentProcessorAnalysis&) const {
egdaniel87509242014-12-17 13:37:13 -0800108 // We never look at the color input
halcanary9d524f22016-03-29 09:03:52 -0700109 return GrXferProcessor::kIgnoreColor_OptFlag;
egdaniel87509242014-12-17 13:37:13 -0800110}
111
cdaltonf4f2b442015-04-23 09:40:23 -0700112void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800113 switch (fRegionOp) {
114 case SkRegion::kReplace_Op:
115 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
116 blendInfo->fDstBlend = kZero_GrBlendCoeff;
117 break;
118 case SkRegion::kIntersect_Op:
119 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
120 blendInfo->fDstBlend = kZero_GrBlendCoeff;
121 break;
122 case SkRegion::kUnion_Op:
123 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
124 blendInfo->fDstBlend = kISC_GrBlendCoeff;
125 break;
126 case SkRegion::kXOR_Op:
127 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
128 blendInfo->fDstBlend = kISC_GrBlendCoeff;
129 break;
130 case SkRegion::kDifference_Op:
131 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
132 blendInfo->fDstBlend = kISC_GrBlendCoeff;
133 break;
134 case SkRegion::kReverseDifference_Op:
135 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
136 blendInfo->fDstBlend = kZero_GrBlendCoeff;
137 break;
138 }
139 blendInfo->fBlendConstant = 0;
140}
141
142///////////////////////////////////////////////////////////////////////////////
143
Brian Salomona1633922017-01-09 11:46:10 -0500144constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
145 bool invertCoverage)
146 : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
egdaniel87509242014-12-17 13:37:13 -0800147
Brian Salomona1633922017-01-09 11:46:10 -0500148const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
149 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
150 // null.
151#ifdef SK_BUILD_FOR_WIN
152#define _CONSTEXPR_
153#else
154#define _CONSTEXPR_ constexpr
155#endif
egdaniel87509242014-12-17 13:37:13 -0800156 switch (regionOp) {
157 case SkRegion::kReplace_Op: {
158 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500159 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
160 SkRegion::kReplace_Op, true);
161 return &gReplaceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800162 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500163 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
164 SkRegion::kReplace_Op, false);
165 return &gReplaceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800166 }
egdaniel87509242014-12-17 13:37:13 -0800167 }
168 case SkRegion::kIntersect_Op: {
169 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500170 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
171 SkRegion::kIntersect_Op, true);
172 return &gIntersectCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800173 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500174 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
175 SkRegion::kIntersect_Op, false);
176 return &gIntersectCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800177 }
egdaniel87509242014-12-17 13:37:13 -0800178 }
179 case SkRegion::kUnion_Op: {
180 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500181 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
182 true);
183 return &gUnionCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800184 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500185 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
186 false);
187 return &gUnionCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800188 }
egdaniel87509242014-12-17 13:37:13 -0800189 }
190 case SkRegion::kXOR_Op: {
191 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500192 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
193 true);
194 return &gXORCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800195 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500196 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
197 false);
198 return &gXORCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800199 }
egdaniel87509242014-12-17 13:37:13 -0800200 }
201 case SkRegion::kDifference_Op: {
202 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500203 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
204 SkRegion::kDifference_Op, true);
205 return &gDifferenceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800206 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500207 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
208 SkRegion::kDifference_Op, false);
209 return &gDifferenceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800210 }
egdaniel87509242014-12-17 13:37:13 -0800211 }
212 case SkRegion::kReverseDifference_Op: {
213 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500214 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
215 SkRegion::kReverseDifference_Op, true);
216 return &gRevDiffCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800217 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500218 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
219 SkRegion::kReverseDifference_Op, false);
220 return &gRevDiffCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800221 }
egdaniel87509242014-12-17 13:37:13 -0800222 }
egdaniel87509242014-12-17 13:37:13 -0800223 }
Brian Salomona1633922017-01-09 11:46:10 -0500224#undef _CONSTEXPR_
225 SkFAIL("Unknown region op.");
226 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800227}
228
Brian Salomon5298dc82017-02-22 11:52:03 -0500229GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(
230 const GrCaps& caps,
231 const FragmentProcessorAnalysis& analysis,
232 bool hasMixedSamples,
233 const DstTexture* dst) const {
cdalton86ae0a92015-06-08 15:11:04 -0700234 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
235 // the future, however we could at some point make this work using an inverted coverage
236 // modulation table. Note that an inverted table still won't work if there are coverage procs.
237 if (fInvertCoverage && hasMixedSamples) {
238 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700239 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700240 }
241
egdaniel41d4f092015-02-09 07:51:00 -0800242 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800243}
244
egdaniel87509242014-12-17 13:37:13 -0800245GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
246
Hal Canary6f6961e2017-01-31 13:50:44 -0500247#if GR_TEST_UTILS
Brian Salomona1633922017-01-09 11:46:10 -0500248const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700249 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
Brian Osman11052242016-10-27 14:47:55 -0400250 bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
Brian Salomona1633922017-01-09 11:46:10 -0500251 return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800252}
Hal Canary6f6961e2017-01-31 13:50:44 -0500253#endif