blob: c1c9425bb7efa5783d50164dc67ef2edb51d1c15 [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"
13#include "GrProcOptInfo.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
ethannicholasde4166a2015-11-30 08:57:38 -080036 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -070037 bool doesStencilWrite,
38 GrColor* color,
egdaniel56cf6dc2015-11-30 10:15:58 -080039 const GrCaps& caps) const override;
egdanielc19cdc22015-05-10 08:45:18 -070040
egdaniel57d3b032015-11-13 11:57:27 -080041 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080042
cdaltonf4f2b442015-04-23 09:40:23 -070043 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
44
mtklein36352bf2015-03-25 18:17:31 -070045 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080046 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
47 return (fRegionOp == xp.fRegionOp &&
48 fInvertCoverage == xp.fInvertCoverage);
49 }
50
51 SkRegion::Op fRegionOp;
52 bool fInvertCoverage;
53
54 typedef GrXferProcessor INHERITED;
55};
56
57///////////////////////////////////////////////////////////////////////////////
58
egdanielfa4cc8b2015-11-13 08:34:52 -080059class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080060public:
61 GLCoverageSetOpXP(const GrProcessor&) {}
62
mtklein36352bf2015-03-25 18:17:31 -070063 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080064
jvanverthcfc18862015-04-28 08:48:20 -070065 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080066 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080067 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080068 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
69 b->add32(key);
70 };
71
72private:
cdaltonedbb31f2015-06-08 12:14:44 -070073 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080074 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080075 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080076
77 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080078 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080079 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080080 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080081 }
82 }
83
egdaniel018fb622015-10-28 07:26:40 -070084 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
egdaniel87509242014-12-17 13:37:13 -080085
egdanielfa4cc8b2015-11-13 08:34:52 -080086 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080087};
88
89///////////////////////////////////////////////////////////////////////////////
90
egdaniel41d4f092015-02-09 07:51:00 -080091CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080092 : fRegionOp(regionOp)
93 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080094 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080095}
96
egdaniel41d4f092015-02-09 07:51:00 -080097CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080098}
99
egdaniel57d3b032015-11-13 11:57:27 -0800100void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
101 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -0800102 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800103}
104
egdaniel57d3b032015-11-13 11:57:27 -0800105GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700106 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800107}
108
109GrXferProcessor::OptFlags
ethannicholasde4166a2015-11-30 08:57:38 -0800110CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -0700111 bool doesStencilWrite,
112 GrColor* color,
egdaniel56cf6dc2015-11-30 10:15:58 -0800113 const GrCaps& caps) const {
egdaniel87509242014-12-17 13:37:13 -0800114 // We never look at the color input
halcanary9d524f22016-03-29 09:03:52 -0700115 return GrXferProcessor::kIgnoreColor_OptFlag;
egdaniel87509242014-12-17 13:37:13 -0800116}
117
cdaltonf4f2b442015-04-23 09:40:23 -0700118void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800119 switch (fRegionOp) {
120 case SkRegion::kReplace_Op:
121 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
122 blendInfo->fDstBlend = kZero_GrBlendCoeff;
123 break;
124 case SkRegion::kIntersect_Op:
125 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
126 blendInfo->fDstBlend = kZero_GrBlendCoeff;
127 break;
128 case SkRegion::kUnion_Op:
129 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
130 blendInfo->fDstBlend = kISC_GrBlendCoeff;
131 break;
132 case SkRegion::kXOR_Op:
133 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
134 blendInfo->fDstBlend = kISC_GrBlendCoeff;
135 break;
136 case SkRegion::kDifference_Op:
137 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
138 blendInfo->fDstBlend = kISC_GrBlendCoeff;
139 break;
140 case SkRegion::kReverseDifference_Op:
141 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
142 blendInfo->fDstBlend = kZero_GrBlendCoeff;
143 break;
144 }
145 blendInfo->fBlendConstant = 0;
146}
147
148///////////////////////////////////////////////////////////////////////////////
149
egdanielf34b2932015-12-01 13:54:06 -0800150class ShaderCSOXferProcessor : public GrXferProcessor {
151public:
152 ShaderCSOXferProcessor(const DstTexture* dstTexture,
153 bool hasMixedSamples,
egdanielf34b2932015-12-01 13:54:06 -0800154 SkRegion::Op regionOp,
155 bool invertCoverage)
156 : INHERITED(dstTexture, true, hasMixedSamples)
157 , fRegionOp(regionOp)
158 , fInvertCoverage(invertCoverage) {
159 this->initClassID<ShaderCSOXferProcessor>();
160 }
161
162 const char* name() const override { return "Coverage Set Op Shader"; }
163
164 GrGLSLXferProcessor* createGLSLInstance() const override;
165
166 SkRegion::Op regionOp() const { return fRegionOp; }
167 bool invertCoverage() const { return fInvertCoverage; }
168
169private:
halcanary9d524f22016-03-29 09:03:52 -0700170 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
egdanielf34b2932015-12-01 13:54:06 -0800171 const GrCaps&) const override {
172 // We never look at the color input
halcanary9d524f22016-03-29 09:03:52 -0700173 return GrXferProcessor::kIgnoreColor_OptFlag;
egdanielf34b2932015-12-01 13:54:06 -0800174 }
175
176 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
177
178 bool onIsEqual(const GrXferProcessor& xpBase) const override {
179 const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
180 return (fRegionOp == xp.fRegionOp &&
181 fInvertCoverage == xp.fInvertCoverage);
182 }
183
184 SkRegion::Op fRegionOp;
185 bool fInvertCoverage;
186
187 typedef GrXferProcessor INHERITED;
188};
189
190///////////////////////////////////////////////////////////////////////////////
191
192class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
193public:
194 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
195 const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
196 b->add32(xp.regionOp());
197 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
198 b->add32(key);
199 }
200
201private:
egdaniel7ea439b2015-12-03 09:20:44 -0800202 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
203 GrGLSLUniformHandler* uniformHandler,
egdanielf34b2932015-12-01 13:54:06 -0800204 const char* srcColor,
205 const char* srcCoverage,
206 const char* dstColor,
207 const char* outColor,
208 const char* outColorSecondary,
209 const GrXferProcessor& proc) override {
210 const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
211
212 if (xp.invertCoverage()) {
213 fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
214 } else {
215 fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
216 }
217
218 GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
219 }
220
221 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
222
223 typedef GrGLSLXferProcessor INHERITED;
224};
225
226///////////////////////////////////////////////////////////////////////////////
227
228void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
229 GrProcessorKeyBuilder* b) const {
230 GLShaderCSOXferProcessor::GenKey(*this, b);
231}
232
233GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
234 return new GLShaderCSOXferProcessor;
235}
236
237///////////////////////////////////////////////////////////////////////////////
238//
egdaniel87509242014-12-17 13:37:13 -0800239GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
240 : fRegionOp(regionOp)
241 , fInvertCoverage(invertCoverage) {
242 this->initClassID<GrCoverageSetOpXPFactory>();
243}
244
245GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
246 switch (regionOp) {
247 case SkRegion::kReplace_Op: {
248 if (invertCoverage) {
249 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
250 return SkRef(&gReplaceCDXPFI);
251 } else {
252 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
253 return SkRef(&gReplaceCDXPF);
254 }
255 break;
256 }
257 case SkRegion::kIntersect_Op: {
258 if (invertCoverage) {
259 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
260 return SkRef(&gIntersectCDXPFI);
261 } else {
262 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
263 return SkRef(&gIntersectCDXPF);
264 }
265 break;
266 }
267 case SkRegion::kUnion_Op: {
268 if (invertCoverage) {
269 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
270 return SkRef(&gUnionCDXPFI);
271 } else {
272 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
273 return SkRef(&gUnionCDXPF);
274 }
275 break;
276 }
277 case SkRegion::kXOR_Op: {
278 if (invertCoverage) {
279 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
280 return SkRef(&gXORCDXPFI);
281 } else {
282 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
283 return SkRef(&gXORCDXPF);
284 }
285 break;
286 }
287 case SkRegion::kDifference_Op: {
288 if (invertCoverage) {
289 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
290 return SkRef(&gDifferenceCDXPFI);
291 } else {
292 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
293 return SkRef(&gDifferenceCDXPF);
294 }
295 break;
296 }
297 case SkRegion::kReverseDifference_Op: {
298 if (invertCoverage) {
299 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
300 return SkRef(&gRevDiffCDXPFI);
301 } else {
302 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
303 return SkRef(&gRevDiffCDXPF);
304 }
305 break;
306 }
307 default:
halcanary96fcdcc2015-08-27 07:41:13 -0700308 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800309 }
310}
311
bsalomon50785a32015-02-06 07:02:37 -0800312GrXferProcessor*
bsalomon4b91f762015-05-19 09:29:46 -0700313GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
ethannicholasde4166a2015-11-30 08:57:38 -0800314 const GrPipelineOptimizations& optimizations,
cdalton86ae0a92015-06-08 15:11:04 -0700315 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700316 const DstTexture* dst) const {
cdalton86ae0a92015-06-08 15:11:04 -0700317 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
318 // the future, however we could at some point make this work using an inverted coverage
319 // modulation table. Note that an inverted table still won't work if there are coverage procs.
320 if (fInvertCoverage && hasMixedSamples) {
321 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700322 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700323 }
324
ethannicholas22793252016-01-30 09:59:10 -0800325 if (optimizations.fOverrides.fUsePLSDstRead) {
326 return new ShaderCSOXferProcessor(dst, hasMixedSamples, fRegionOp, fInvertCoverage);
327 }
egdaniel41d4f092015-02-09 07:51:00 -0800328 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800329}
330
cdalton1fa45722015-06-02 10:43:39 -0700331void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
332 InvariantBlendedColor* blendedColor) const {
333 blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
334 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
egdaniel87509242014-12-17 13:37:13 -0800335}
336
egdaniel87509242014-12-17 13:37:13 -0800337GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
338
bsalomonc21b09e2015-08-28 18:46:56 -0700339const GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700340 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
cdaltonc94cd7c2015-11-12 12:11:04 -0800341 bool invertCoverage = !d->fRenderTarget->hasMixedSamples() && d->fRandom->nextBool();
egdaniel87509242014-12-17 13:37:13 -0800342 return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
343}