blob: c7226fc80a02ac03a68be764131e2195d13b2120 [file] [log] [blame]
egdaniel87509242014-12-17 13:37:13 -08001
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "effects/GrCoverageSetOpXP.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070010#include "GrCaps.h"
egdaniel87509242014-12-17 13:37:13 -080011#include "GrColor.h"
egdaniel87509242014-12-17 13:37:13 -080012#include "GrProcessor.h"
13#include "GrProcOptInfo.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLProgramBuilder.h"
15#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdanielfa4cc8b2015-11-13 08:34:52 -080016#include "glsl/GrGLSLXferProcessor.h"
egdaniel87509242014-12-17 13:37:13 -080017
egdaniel41d4f092015-02-09 07:51:00 -080018class CoverageSetOpXP : public GrXferProcessor {
egdaniel87509242014-12-17 13:37:13 -080019public:
egdaniel41d4f092015-02-09 07:51:00 -080020 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
halcanary385fe4d2015-08-26 13:07:48 -070021 return new CoverageSetOpXP(regionOp, invertCoverage);
egdaniel41d4f092015-02-09 07:51:00 -080022 }
egdaniel87509242014-12-17 13:37:13 -080023
mtklein36352bf2015-03-25 18:17:31 -070024 ~CoverageSetOpXP() override;
egdaniel41d4f092015-02-09 07:51:00 -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:
33 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
34
ethannicholasde4166a2015-11-30 08:57:38 -080035 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -070036 bool doesStencilWrite,
37 GrColor* color,
bsalomon4b91f762015-05-19 09:29:46 -070038 const GrCaps& caps) override;
egdanielc19cdc22015-05-10 08:45:18 -070039
egdaniel57d3b032015-11-13 11:57:27 -080040 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080041
cdaltonf4f2b442015-04-23 09:40:23 -070042 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
43
mtklein36352bf2015-03-25 18:17:31 -070044 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080045 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
46 return (fRegionOp == xp.fRegionOp &&
47 fInvertCoverage == xp.fInvertCoverage);
48 }
49
50 SkRegion::Op fRegionOp;
51 bool fInvertCoverage;
52
53 typedef GrXferProcessor INHERITED;
54};
55
56///////////////////////////////////////////////////////////////////////////////
57
egdanielfa4cc8b2015-11-13 08:34:52 -080058class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080059public:
60 GLCoverageSetOpXP(const GrProcessor&) {}
61
mtklein36352bf2015-03-25 18:17:31 -070062 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080063
jvanverthcfc18862015-04-28 08:48:20 -070064 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080065 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080066 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080067 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
68 b->add32(key);
69 };
70
71private:
cdaltonedbb31f2015-06-08 12:14:44 -070072 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080073 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080074 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080075
76 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080077 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080078 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080079 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080080 }
81 }
82
egdaniel018fb622015-10-28 07:26:40 -070083 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
egdaniel87509242014-12-17 13:37:13 -080084
egdanielfa4cc8b2015-11-13 08:34:52 -080085 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080086};
87
88///////////////////////////////////////////////////////////////////////////////
89
egdaniel41d4f092015-02-09 07:51:00 -080090CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080091 : fRegionOp(regionOp)
92 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080093 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080094}
95
egdaniel41d4f092015-02-09 07:51:00 -080096CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080097}
98
egdaniel57d3b032015-11-13 11:57:27 -080099void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
100 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -0800101 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800102}
103
egdaniel57d3b032015-11-13 11:57:27 -0800104GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700105 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800106}
107
108GrXferProcessor::OptFlags
ethannicholasde4166a2015-11-30 08:57:38 -0800109CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -0700110 bool doesStencilWrite,
111 GrColor* color,
bsalomon4b91f762015-05-19 09:29:46 -0700112 const GrCaps& caps) {
egdaniel87509242014-12-17 13:37:13 -0800113 // We never look at the color input
114 return GrXferProcessor::kIgnoreColor_OptFlag;
115}
116
cdaltonf4f2b442015-04-23 09:40:23 -0700117void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800118 switch (fRegionOp) {
119 case SkRegion::kReplace_Op:
120 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
121 blendInfo->fDstBlend = kZero_GrBlendCoeff;
122 break;
123 case SkRegion::kIntersect_Op:
124 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
125 blendInfo->fDstBlend = kZero_GrBlendCoeff;
126 break;
127 case SkRegion::kUnion_Op:
128 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
129 blendInfo->fDstBlend = kISC_GrBlendCoeff;
130 break;
131 case SkRegion::kXOR_Op:
132 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
133 blendInfo->fDstBlend = kISC_GrBlendCoeff;
134 break;
135 case SkRegion::kDifference_Op:
136 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
137 blendInfo->fDstBlend = kISC_GrBlendCoeff;
138 break;
139 case SkRegion::kReverseDifference_Op:
140 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
141 blendInfo->fDstBlend = kZero_GrBlendCoeff;
142 break;
143 }
144 blendInfo->fBlendConstant = 0;
145}
146
147///////////////////////////////////////////////////////////////////////////////
148
149GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
150 : fRegionOp(regionOp)
151 , fInvertCoverage(invertCoverage) {
152 this->initClassID<GrCoverageSetOpXPFactory>();
153}
154
155GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
156 switch (regionOp) {
157 case SkRegion::kReplace_Op: {
158 if (invertCoverage) {
159 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
160 return SkRef(&gReplaceCDXPFI);
161 } else {
162 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
163 return SkRef(&gReplaceCDXPF);
164 }
165 break;
166 }
167 case SkRegion::kIntersect_Op: {
168 if (invertCoverage) {
169 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
170 return SkRef(&gIntersectCDXPFI);
171 } else {
172 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
173 return SkRef(&gIntersectCDXPF);
174 }
175 break;
176 }
177 case SkRegion::kUnion_Op: {
178 if (invertCoverage) {
179 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
180 return SkRef(&gUnionCDXPFI);
181 } else {
182 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
183 return SkRef(&gUnionCDXPF);
184 }
185 break;
186 }
187 case SkRegion::kXOR_Op: {
188 if (invertCoverage) {
189 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
190 return SkRef(&gXORCDXPFI);
191 } else {
192 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
193 return SkRef(&gXORCDXPF);
194 }
195 break;
196 }
197 case SkRegion::kDifference_Op: {
198 if (invertCoverage) {
199 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
200 return SkRef(&gDifferenceCDXPFI);
201 } else {
202 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
203 return SkRef(&gDifferenceCDXPF);
204 }
205 break;
206 }
207 case SkRegion::kReverseDifference_Op: {
208 if (invertCoverage) {
209 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
210 return SkRef(&gRevDiffCDXPFI);
211 } else {
212 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
213 return SkRef(&gRevDiffCDXPF);
214 }
215 break;
216 }
217 default:
halcanary96fcdcc2015-08-27 07:41:13 -0700218 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800219 }
220}
221
bsalomon50785a32015-02-06 07:02:37 -0800222GrXferProcessor*
bsalomon4b91f762015-05-19 09:29:46 -0700223GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
ethannicholasde4166a2015-11-30 08:57:38 -0800224 const GrPipelineOptimizations& optimizations,
cdalton86ae0a92015-06-08 15:11:04 -0700225 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700226 const DstTexture* dst) const {
cdalton86ae0a92015-06-08 15:11:04 -0700227 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
228 // the future, however we could at some point make this work using an inverted coverage
229 // modulation table. Note that an inverted table still won't work if there are coverage procs.
230 if (fInvertCoverage && hasMixedSamples) {
231 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700232 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700233 }
234
egdaniel41d4f092015-02-09 07:51:00 -0800235 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800236}
237
cdalton1fa45722015-06-02 10:43:39 -0700238void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
239 InvariantBlendedColor* blendedColor) const {
240 blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
241 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
egdaniel87509242014-12-17 13:37:13 -0800242}
243
egdaniel87509242014-12-17 13:37:13 -0800244GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
245
bsalomonc21b09e2015-08-28 18:46:56 -0700246const GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700247 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
cdaltonc94cd7c2015-11-12 12:11:04 -0800248 bool invertCoverage = !d->fRenderTarget->hasMixedSamples() && d->fRandom->nextBool();
egdaniel87509242014-12-17 13:37:13 -0800249 return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
250}
251