blob: 8c98c6c84324a01c64a6ddd106352c60168d1c99 [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"
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
ethannicholasde4166a2015-11-30 08:57:38 -080037 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -070038 bool doesStencilWrite,
39 GrColor* color,
egdaniel56cf6dc2015-11-30 10:15:58 -080040 const GrCaps& caps) const override;
egdanielc19cdc22015-05-10 08:45:18 -070041
egdaniel57d3b032015-11-13 11:57:27 -080042 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080043
cdaltonf4f2b442015-04-23 09:40:23 -070044 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
45
mtklein36352bf2015-03-25 18:17:31 -070046 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080047 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
48 return (fRegionOp == xp.fRegionOp &&
49 fInvertCoverage == xp.fInvertCoverage);
50 }
51
52 SkRegion::Op fRegionOp;
53 bool fInvertCoverage;
54
55 typedef GrXferProcessor INHERITED;
56};
57
58///////////////////////////////////////////////////////////////////////////////
59
egdanielfa4cc8b2015-11-13 08:34:52 -080060class GLCoverageSetOpXP : public GrGLSLXferProcessor {
egdaniel41d4f092015-02-09 07:51:00 -080061public:
62 GLCoverageSetOpXP(const GrProcessor&) {}
63
mtklein36352bf2015-03-25 18:17:31 -070064 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080065
jvanverthcfc18862015-04-28 08:48:20 -070066 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080067 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080068 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080069 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
70 b->add32(key);
71 };
72
73private:
cdaltonedbb31f2015-06-08 12:14:44 -070074 void emitOutputsForBlendState(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080075 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel4ca2e602015-11-18 08:01:26 -080076 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
egdaniel87509242014-12-17 13:37:13 -080077
78 if (xp.invertCoverage()) {
egdaniel4ca2e602015-11-18 08:01:26 -080079 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080080 } else {
egdaniel4ca2e602015-11-18 08:01:26 -080081 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
egdaniel87509242014-12-17 13:37:13 -080082 }
83 }
84
egdaniel018fb622015-10-28 07:26:40 -070085 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
egdaniel87509242014-12-17 13:37:13 -080086
egdanielfa4cc8b2015-11-13 08:34:52 -080087 typedef GrGLSLXferProcessor INHERITED;
egdaniel87509242014-12-17 13:37:13 -080088};
89
90///////////////////////////////////////////////////////////////////////////////
91
egdaniel41d4f092015-02-09 07:51:00 -080092CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080093 : fRegionOp(regionOp)
94 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080095 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080096}
97
egdaniel41d4f092015-02-09 07:51:00 -080098CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -080099}
100
egdaniel57d3b032015-11-13 11:57:27 -0800101void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
102 GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -0800103 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800104}
105
egdaniel57d3b032015-11-13 11:57:27 -0800106GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700107 return new GLCoverageSetOpXP(*this);
egdaniel87509242014-12-17 13:37:13 -0800108}
109
110GrXferProcessor::OptFlags
ethannicholasde4166a2015-11-30 08:57:38 -0800111CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
egdanielc19cdc22015-05-10 08:45:18 -0700112 bool doesStencilWrite,
113 GrColor* color,
egdaniel56cf6dc2015-11-30 10:15:58 -0800114 const GrCaps& caps) const {
egdaniel87509242014-12-17 13:37:13 -0800115 // We never look at the color input
116 return GrXferProcessor::kIgnoreColor_OptFlag;
117}
118
cdaltonf4f2b442015-04-23 09:40:23 -0700119void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800120 switch (fRegionOp) {
121 case SkRegion::kReplace_Op:
122 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
123 blendInfo->fDstBlend = kZero_GrBlendCoeff;
124 break;
125 case SkRegion::kIntersect_Op:
126 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
127 blendInfo->fDstBlend = kZero_GrBlendCoeff;
128 break;
129 case SkRegion::kUnion_Op:
130 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
131 blendInfo->fDstBlend = kISC_GrBlendCoeff;
132 break;
133 case SkRegion::kXOR_Op:
134 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
135 blendInfo->fDstBlend = kISC_GrBlendCoeff;
136 break;
137 case SkRegion::kDifference_Op:
138 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
139 blendInfo->fDstBlend = kISC_GrBlendCoeff;
140 break;
141 case SkRegion::kReverseDifference_Op:
142 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
143 blendInfo->fDstBlend = kZero_GrBlendCoeff;
144 break;
145 }
146 blendInfo->fBlendConstant = 0;
147}
148
149///////////////////////////////////////////////////////////////////////////////
150
egdanielf34b2932015-12-01 13:54:06 -0800151class ShaderCSOXferProcessor : public GrXferProcessor {
152public:
153 ShaderCSOXferProcessor(const DstTexture* dstTexture,
154 bool hasMixedSamples,
egdanielf34b2932015-12-01 13:54:06 -0800155 SkRegion::Op regionOp,
156 bool invertCoverage)
157 : INHERITED(dstTexture, true, hasMixedSamples)
158 , fRegionOp(regionOp)
159 , fInvertCoverage(invertCoverage) {
160 this->initClassID<ShaderCSOXferProcessor>();
161 }
162
163 const char* name() const override { return "Coverage Set Op Shader"; }
164
165 GrGLSLXferProcessor* createGLSLInstance() const override;
166
167 SkRegion::Op regionOp() const { return fRegionOp; }
168 bool invertCoverage() const { return fInvertCoverage; }
169
170private:
171 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
172 const GrCaps&) const override {
173 // We never look at the color input
174 return GrXferProcessor::kIgnoreColor_OptFlag;
175 }
176
177 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
178
179 bool onIsEqual(const GrXferProcessor& xpBase) const override {
180 const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
181 return (fRegionOp == xp.fRegionOp &&
182 fInvertCoverage == xp.fInvertCoverage);
183 }
184
185 SkRegion::Op fRegionOp;
186 bool fInvertCoverage;
187
188 typedef GrXferProcessor INHERITED;
189};
190
191///////////////////////////////////////////////////////////////////////////////
192
193class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
194public:
195 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
196 const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
197 b->add32(xp.regionOp());
198 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
199 b->add32(key);
200 }
201
202private:
egdaniel7ea439b2015-12-03 09:20:44 -0800203 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
204 GrGLSLUniformHandler* uniformHandler,
egdanielf34b2932015-12-01 13:54:06 -0800205 const char* srcColor,
206 const char* srcCoverage,
207 const char* dstColor,
208 const char* outColor,
209 const char* outColorSecondary,
210 const GrXferProcessor& proc) override {
211 const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
212
213 if (xp.invertCoverage()) {
214 fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
215 } else {
216 fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
217 }
218
219 GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
220 }
221
222 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
223
224 typedef GrGLSLXferProcessor INHERITED;
225};
226
227///////////////////////////////////////////////////////////////////////////////
228
229void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
230 GrProcessorKeyBuilder* b) const {
231 GLShaderCSOXferProcessor::GenKey(*this, b);
232}
233
234GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
235 return new GLShaderCSOXferProcessor;
236}
237
238///////////////////////////////////////////////////////////////////////////////
239//
egdaniel87509242014-12-17 13:37:13 -0800240GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
241 : fRegionOp(regionOp)
242 , fInvertCoverage(invertCoverage) {
243 this->initClassID<GrCoverageSetOpXPFactory>();
244}
245
246GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
247 switch (regionOp) {
248 case SkRegion::kReplace_Op: {
249 if (invertCoverage) {
250 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
251 return SkRef(&gReplaceCDXPFI);
252 } else {
253 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
254 return SkRef(&gReplaceCDXPF);
255 }
256 break;
257 }
258 case SkRegion::kIntersect_Op: {
259 if (invertCoverage) {
260 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
261 return SkRef(&gIntersectCDXPFI);
262 } else {
263 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
264 return SkRef(&gIntersectCDXPF);
265 }
266 break;
267 }
268 case SkRegion::kUnion_Op: {
269 if (invertCoverage) {
270 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
271 return SkRef(&gUnionCDXPFI);
272 } else {
273 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
274 return SkRef(&gUnionCDXPF);
275 }
276 break;
277 }
278 case SkRegion::kXOR_Op: {
279 if (invertCoverage) {
280 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
281 return SkRef(&gXORCDXPFI);
282 } else {
283 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
284 return SkRef(&gXORCDXPF);
285 }
286 break;
287 }
288 case SkRegion::kDifference_Op: {
289 if (invertCoverage) {
290 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
291 return SkRef(&gDifferenceCDXPFI);
292 } else {
293 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
294 return SkRef(&gDifferenceCDXPF);
295 }
296 break;
297 }
298 case SkRegion::kReverseDifference_Op: {
299 if (invertCoverage) {
300 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
301 return SkRef(&gRevDiffCDXPFI);
302 } else {
303 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
304 return SkRef(&gRevDiffCDXPF);
305 }
306 break;
307 }
308 default:
halcanary96fcdcc2015-08-27 07:41:13 -0700309 return nullptr;
egdaniel87509242014-12-17 13:37:13 -0800310 }
311}
312
bsalomon50785a32015-02-06 07:02:37 -0800313GrXferProcessor*
bsalomon4b91f762015-05-19 09:29:46 -0700314GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
ethannicholasde4166a2015-11-30 08:57:38 -0800315 const GrPipelineOptimizations& optimizations,
cdalton86ae0a92015-06-08 15:11:04 -0700316 bool hasMixedSamples,
bsalomon6a44c6a2015-05-26 09:49:05 -0700317 const DstTexture* dst) const {
cdalton86ae0a92015-06-08 15:11:04 -0700318 // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
319 // the future, however we could at some point make this work using an inverted coverage
320 // modulation table. Note that an inverted table still won't work if there are coverage procs.
321 if (fInvertCoverage && hasMixedSamples) {
322 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700323 return nullptr;
cdalton86ae0a92015-06-08 15:11:04 -0700324 }
325
ethannicholas22793252016-01-30 09:59:10 -0800326 if (optimizations.fOverrides.fUsePLSDstRead) {
327 return new ShaderCSOXferProcessor(dst, hasMixedSamples, fRegionOp, fInvertCoverage);
328 }
egdaniel41d4f092015-02-09 07:51:00 -0800329 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800330}
331
cdalton1fa45722015-06-02 10:43:39 -0700332void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
333 InvariantBlendedColor* blendedColor) const {
334 blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
335 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
egdaniel87509242014-12-17 13:37:13 -0800336}
337
egdaniel87509242014-12-17 13:37:13 -0800338GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
339
bsalomonc21b09e2015-08-28 18:46:56 -0700340const GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700341 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
cdaltonc94cd7c2015-11-12 12:11:04 -0800342 bool invertCoverage = !d->fRenderTarget->hasMixedSamples() && d->fRandom->nextBool();
egdaniel87509242014-12-17 13:37:13 -0800343 return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
344}
345