blob: 4d4b00a379e88490afc8cdef485e532113cf2a0d [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 Salomon94efbf52016-11-29 13:43:05 -050036 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080037
cdaltonf4f2b442015-04-23 09:40:23 -070038 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
39
mtklein36352bf2015-03-25 18:17:31 -070040 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080041 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
42 return (fRegionOp == xp.fRegionOp &&
43 fInvertCoverage == xp.fInvertCoverage);
44 }
45
46 SkRegion::Op fRegionOp;
47 bool fInvertCoverage;
48
49 typedef GrXferProcessor INHERITED;
50};
51
52///////////////////////////////////////////////////////////////////////////////
53
egdanielfa4cc8b2015-11-13 08:34:52 -080054class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080055public:
56 GLCoverageSetOpXP(const GrProcessor&) {}
57
mtklein36352bf2015-03-25 18:17:31 -070058 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080059
Brian Salomon94efbf52016-11-29 13:43:05 -050060 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080061 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080062 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080063 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
64 b->add32(key);
Mike Kleinfc6c37b2016-09-27 09:34:10 -040065 }
bsalomon50785a32015-02-06 07:02:37 -080066
67private:
cdaltonedbb31f2015-06-08 12:14:44 -070068 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080069 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080070 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080071
72 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080073 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080074 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080075 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080076 }
77 }
78
Mike Kleinfc6c37b2016-09-27 09:34:10 -040079 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
egdaniel87509242014-12-17 13:37:13 -080080
egdanielfa4cc8b2015-11-13 08:34:52 -080081 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080082};
83
84///////////////////////////////////////////////////////////////////////////////
85
egdaniel41d4f092015-02-09 07:51:00 -080086CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080087 : fRegionOp(regionOp)
88 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080089 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080090}
91
egdaniel41d4f092015-02-09 07:51:00 -080092CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080093}
94
Brian Salomon94efbf52016-11-29 13:43:05 -050095void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080096 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -080097 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -080098}
99
egdaniel57d3b032015-11-13 11:57:27 -0800100GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700101 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800102}
103
cdaltonf4f2b442015-04-23 09:40:23 -0700104void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800105 switch (fRegionOp) {
106 case SkRegion::kReplace_Op:
107 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
108 blendInfo->fDstBlend = kZero_GrBlendCoeff;
109 break;
110 case SkRegion::kIntersect_Op:
111 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
112 blendInfo->fDstBlend = kZero_GrBlendCoeff;
113 break;
114 case SkRegion::kUnion_Op:
115 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
116 blendInfo->fDstBlend = kISC_GrBlendCoeff;
117 break;
118 case SkRegion::kXOR_Op:
119 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
120 blendInfo->fDstBlend = kISC_GrBlendCoeff;
121 break;
122 case SkRegion::kDifference_Op:
123 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
124 blendInfo->fDstBlend = kISC_GrBlendCoeff;
125 break;
126 case SkRegion::kReverseDifference_Op:
127 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
128 blendInfo->fDstBlend = kZero_GrBlendCoeff;
129 break;
130 }
131 blendInfo->fBlendConstant = 0;
132}
133
134///////////////////////////////////////////////////////////////////////////////
135
Brian Salomona1633922017-01-09 11:46:10 -0500136constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
137 bool invertCoverage)
138 : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
egdaniel87509242014-12-17 13:37:13 -0800139
Brian Salomona1633922017-01-09 11:46:10 -0500140const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
141 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
142 // null.
143#ifdef SK_BUILD_FOR_WIN
144#define _CONSTEXPR_
145#else
146#define _CONSTEXPR_ constexpr
147#endif
egdaniel87509242014-12-17 13:37:13 -0800148 switch (regionOp) {
149 case SkRegion::kReplace_Op: {
150 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500151 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
152 SkRegion::kReplace_Op, true);
153 return &gReplaceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800154 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500155 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
156 SkRegion::kReplace_Op, false);
157 return &gReplaceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800158 }
egdaniel87509242014-12-17 13:37:13 -0800159 }
160 case SkRegion::kIntersect_Op: {
161 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500162 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
163 SkRegion::kIntersect_Op, true);
164 return &gIntersectCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800165 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500166 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
167 SkRegion::kIntersect_Op, false);
168 return &gIntersectCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800169 }
egdaniel87509242014-12-17 13:37:13 -0800170 }
171 case SkRegion::kUnion_Op: {
172 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500173 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
174 true);
175 return &gUnionCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800176 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500177 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
178 false);
179 return &gUnionCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800180 }
egdaniel87509242014-12-17 13:37:13 -0800181 }
182 case SkRegion::kXOR_Op: {
183 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500184 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
185 true);
186 return &gXORCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800187 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500188 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
189 false);
190 return &gXORCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800191 }
egdaniel87509242014-12-17 13:37:13 -0800192 }
193 case SkRegion::kDifference_Op: {
194 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500195 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
196 SkRegion::kDifference_Op, true);
197 return &gDifferenceCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800198 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500199 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
200 SkRegion::kDifference_Op, false);
201 return &gDifferenceCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800202 }
egdaniel87509242014-12-17 13:37:13 -0800203 }
204 case SkRegion::kReverseDifference_Op: {
205 if (invertCoverage) {
Brian Salomona1633922017-01-09 11:46:10 -0500206 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
207 SkRegion::kReverseDifference_Op, true);
208 return &gRevDiffCDXPFI;
egdaniel87509242014-12-17 13:37:13 -0800209 } else {
Brian Salomona1633922017-01-09 11:46:10 -0500210 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
211 SkRegion::kReverseDifference_Op, false);
212 return &gRevDiffCDXPF;
egdaniel87509242014-12-17 13:37:13 -0800213 }
egdaniel87509242014-12-17 13:37:13 -0800214 }
egdaniel87509242014-12-17 13:37:13 -0800215 }
Brian Salomona1633922017-01-09 11:46:10 -0500216#undef _CONSTEXPR_
217 SkFAIL("Unknown region op.");
218 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800219}
220
Brian Salomon1c6025c2017-03-29 14:25:04 -0400221GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
Brian Salomona811b122017-03-30 08:21:32 -0400222 const GrProcessorAnalysisColor&,
223 GrProcessorAnalysisCoverage,
Brian Salomon18dfa982017-04-03 16:57:43 -0400224 bool hasMixedSamples) const {
cdalton86ae0a92015-06-08 15:11:04 -0700225 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
226 // the future, however we could at some point make this work using an inverted coverage
227 // modulation table. Note that an inverted table still won't work if there are coverage procs.
228 if (fInvertCoverage && hasMixedSamples) {
229 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700230 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700231 }
232
egdaniel41d4f092015-02-09 07:51:00 -0800233 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800234}
235
egdaniel87509242014-12-17 13:37:13 -0800236GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
237
Hal Canary6f6961e2017-01-31 13:50:44 -0500238#if GR_TEST_UTILS
Brian Salomona1633922017-01-09 11:46:10 -0500239const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700240 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
Brian Osman11052242016-10-27 14:47:55 -0400241 bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
Brian Salomona1633922017-01-09 11:46:10 -0500242 return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800243}
Hal Canary6f6961e2017-01-31 13:50:44 -0500244#endif