blob: 52ebaad3097f1bfc29a5eb85175f3ed93d7acd53 [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"
Brian Osman11052242016-10-27 14:47:55 -040011#include "GrRenderTargetContext.h"
ethannicholas22793252016-01-30 09:59:10 -080012#include "GrPipeline.h"
egdaniel87509242014-12-17 13:37:13 -080013#include "GrProcessor.h"
14#include "GrProcOptInfo.h"
egdanielf34b2932015-12-01 13:54:06 -080015#include "glsl/GrGLSLBlend.h"
egdaniel2d721d32015-11-11 13:06:05 -080016#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel7ea439b2015-12-03 09:20:44 -080017#include "glsl/GrGLSLUniformHandler.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080018#include "glsl/GrGLSLXferProcessor.h"
egdaniel87509242014-12-17 13:37:13 -080019
egdaniel41d4f092015-02-09 07:51:00 -080020class CoverageSetOpXP : public GrXferProcessor {
egdaniel87509242014-12-17 13:37:13 -080021public:
egdaniel41d4f092015-02-09 07:51:00 -080022 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
halcanary385fe4d2015-08-26 13:07:48 -070023 return new CoverageSetOpXP(regionOp, invertCoverage);
egdaniel41d4f092015-02-09 07:51:00 -080024 }
egdaniel87509242014-12-17 13:37:13 -080025
mtklein36352bf2015-03-25 18:17:31 -070026 ~CoverageSetOpXP() override;
egdaniel41d4f092015-02-09 07:51:00 -080027
mtklein36352bf2015-03-25 18:17:31 -070028 const char* name() const override { return "Coverage Set Op"; }
egdaniel41d4f092015-02-09 07:51:00 -080029
egdaniel57d3b032015-11-13 11:57:27 -080030 GrGLSLXferProcessor* createGLSLInstance() const override;
egdaniel41d4f092015-02-09 07:51:00 -080031
egdaniel41d4f092015-02-09 07:51:00 -080032 bool invertCoverage() const { return fInvertCoverage; }
33
34private:
35 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
36
Brian Salomon1c10fdd2017-03-03 14:30:15 -050037 GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
egdanielc19cdc22015-05-10 08:45:18 -070038
Brian Salomon94efbf52016-11-29 13:43:05 -050039 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080040
cdaltonf4f2b442015-04-23 09:40:23 -070041 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
42
mtklein36352bf2015-03-25 18:17:31 -070043 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080044 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
45 return (fRegionOp == xp.fRegionOp &&
46 fInvertCoverage == xp.fInvertCoverage);
47 }
48
49 SkRegion::Op fRegionOp;
50 bool fInvertCoverage;
51
52 typedef GrXferProcessor INHERITED;
53};
54
55///////////////////////////////////////////////////////////////////////////////
56
egdanielfa4cc8b2015-11-13 08:34:52 -080057class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080058public:
59 GLCoverageSetOpXP(const GrProcessor&) {}
60
mtklein36352bf2015-03-25 18:17:31 -070061 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080062
Brian Salomon94efbf52016-11-29 13:43:05 -050063 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080064 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080065 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080066 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
67 b->add32(key);
Mike Kleinfc6c37b2016-09-27 09:34:10 -040068 }
bsalomon50785a32015-02-06 07:02:37 -080069
70private:
cdaltonedbb31f2015-06-08 12:14:44 -070071 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080072 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080073 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080074
75 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080076 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080077 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080078 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080079 }
80 }
81
Mike Kleinfc6c37b2016-09-27 09:34:10 -040082 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
egdaniel87509242014-12-17 13:37:13 -080083
egdanielfa4cc8b2015-11-13 08:34:52 -080084 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080085};
86
87///////////////////////////////////////////////////////////////////////////////
88
egdaniel41d4f092015-02-09 07:51:00 -080089CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080090 : fRegionOp(regionOp)
91 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080092 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080093}
94
egdaniel41d4f092015-02-09 07:51:00 -080095CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080096}
97
Brian Salomon94efbf52016-11-29 13:43:05 -050098void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080099 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -0800100 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800101}
102
egdaniel57d3b032015-11-13 11:57:27 -0800103GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700104 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800105}
106
Brian Salomon5298dc82017-02-22 11:52:03 -0500107GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(
Brian Salomon1c10fdd2017-03-03 14:30:15 -0500108 const FragmentProcessorAnalysis&) const {
egdaniel87509242014-12-17 13:37:13 -0800109 // We never look at the color input
halcanary9d524f22016-03-29 09:03:52 -0700110 return GrXferProcessor::kIgnoreColor_OptFlag;
egdaniel87509242014-12-17 13:37:13 -0800111}
112
cdaltonf4f2b442015-04-23 09:40:23 -0700113void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800114 switch (fRegionOp) {
115 case SkRegion::kReplace_Op:
116 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
117 blendInfo->fDstBlend = kZero_GrBlendCoeff;
118 break;
119 case SkRegion::kIntersect_Op:
120 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
121 blendInfo->fDstBlend = kZero_GrBlendCoeff;
122 break;
123 case SkRegion::kUnion_Op:
124 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
125 blendInfo->fDstBlend = kISC_GrBlendCoeff;
126 break;
127 case SkRegion::kXOR_Op:
128 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
129 blendInfo->fDstBlend = kISC_GrBlendCoeff;
130 break;
131 case SkRegion::kDifference_Op:
132 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
133 blendInfo->fDstBlend = kISC_GrBlendCoeff;
134 break;
135 case SkRegion::kReverseDifference_Op:
136 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
137 blendInfo->fDstBlend = kZero_GrBlendCoeff;
138 break;
139 }
140 blendInfo->fBlendConstant = 0;
141}
142
143///////////////////////////////////////////////////////////////////////////////
144
Brian Salomona1633922017-01-09 11:46:10 -0500145constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
146 bool invertCoverage)
147 : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
egdaniel87509242014-12-17 13:37:13 -0800148
Brian Salomona1633922017-01-09 11:46:10 -0500149const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
150 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
151 // null.
152#ifdef SK_BUILD_FOR_WIN
153#define _CONSTEXPR_
154#else
155#define _CONSTEXPR_ constexpr
156#endif
egdaniel87509242014-12-17 13:37:13 -0800157 switch (regionOp) {
158 case SkRegion::kReplace_Op: {
159 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500160 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
161 SkRegion::kReplace_Op, true);
162 return &gReplaceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800163 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500164 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
165 SkRegion::kReplace_Op, false);
166 return &gReplaceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800167 }
egdaniel87509242014-12-17 13:37:13 -0800168 }
169 case SkRegion::kIntersect_Op: {
170 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500171 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
172 SkRegion::kIntersect_Op, true);
173 return &gIntersectCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800174 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500175 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
176 SkRegion::kIntersect_Op, false);
177 return &gIntersectCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800178 }
egdaniel87509242014-12-17 13:37:13 -0800179 }
180 case SkRegion::kUnion_Op: {
181 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500182 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
183 true);
184 return &gUnionCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800185 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500186 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
187 false);
188 return &gUnionCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800189 }
egdaniel87509242014-12-17 13:37:13 -0800190 }
191 case SkRegion::kXOR_Op: {
192 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500193 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
194 true);
195 return &gXORCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800196 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500197 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
198 false);
199 return &gXORCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800200 }
egdaniel87509242014-12-17 13:37:13 -0800201 }
202 case SkRegion::kDifference_Op: {
203 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500204 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
205 SkRegion::kDifference_Op, true);
206 return &gDifferenceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800207 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500208 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
209 SkRegion::kDifference_Op, false);
210 return &gDifferenceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800211 }
egdaniel87509242014-12-17 13:37:13 -0800212 }
213 case SkRegion::kReverseDifference_Op: {
214 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500215 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
216 SkRegion::kReverseDifference_Op, true);
217 return &gRevDiffCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800218 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500219 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
220 SkRegion::kReverseDifference_Op, false);
221 return &gRevDiffCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800222 }
egdaniel87509242014-12-17 13:37:13 -0800223 }
egdaniel87509242014-12-17 13:37:13 -0800224 }
Brian Salomona1633922017-01-09 11:46:10 -0500225#undef _CONSTEXPR_
226 SkFAIL("Unknown region op.");
227 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800228}
229
Brian Salomon5298dc82017-02-22 11:52:03 -0500230GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(
231 const GrCaps& caps,
232 const FragmentProcessorAnalysis& analysis,
233 bool hasMixedSamples,
234 const DstTexture* dst) const {
cdalton86ae0a92015-06-08 15:11:04 -0700235 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
236 // the future, however we could at some point make this work using an inverted coverage
237 // modulation table. Note that an inverted table still won't work if there are coverage procs.
238 if (fInvertCoverage && hasMixedSamples) {
239 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700240 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700241 }
242
egdaniel41d4f092015-02-09 07:51:00 -0800243 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800244}
245
egdaniel87509242014-12-17 13:37:13 -0800246GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
247
Hal Canary6f6961e2017-01-31 13:50:44 -0500248#if GR_TEST_UTILS
Brian Salomona1633922017-01-09 11:46:10 -0500249const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700250 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
Brian Osman11052242016-10-27 14:47:55 -0400251 bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
Brian Salomona1633922017-01-09 11:46:10 -0500252 return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800253}
Hal Canary6f6961e2017-01-31 13:50:44 -0500254#endif