219ed0b505c98b1052b82ae9b3b99ccf4b590efe
[platform/upstream/libSkiaSharp.git] / src / gpu / effects / GrCoverageSetOpXP.cpp
1
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"
10 #include "GrCaps.h"
11 #include "GrColor.h"
12 #include "GrProcessor.h"
13 #include "GrProcOptInfo.h"
14 #include "glsl/GrGLSLBlend.h"
15 #include "glsl/GrGLSLProgramBuilder.h"
16 #include "glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "glsl/GrGLSLXferProcessor.h"
18
19 class CoverageSetOpXP : public GrXferProcessor {
20 public:
21     static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
22         return new CoverageSetOpXP(regionOp, invertCoverage);
23     }
24
25     ~CoverageSetOpXP() override;
26
27     const char* name() const override { return "Coverage Set Op"; }
28
29     GrGLSLXferProcessor* createGLSLInstance() const override;
30
31     bool invertCoverage() const { return fInvertCoverage; }
32
33 private:
34     CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
35
36     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
37                                                  bool doesStencilWrite,
38                                                  GrColor* color,
39                                                  const GrCaps& caps) const override;
40
41     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
42
43     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
44
45     bool onIsEqual(const GrXferProcessor& xpBase) const override {
46         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
59 class GLCoverageSetOpXP : public GrGLSLXferProcessor {
60 public:
61     GLCoverageSetOpXP(const GrProcessor&) {}
62
63     ~GLCoverageSetOpXP() override {}
64
65     static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
66                        GrProcessorKeyBuilder* b) {
67         const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
68         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
69         b->add32(key);
70     };
71
72 private:
73     void emitOutputsForBlendState(const EmitArgs& args) override {
74         const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
75         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
76
77         if (xp.invertCoverage()) {
78             fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
79         } else {
80             fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
81         }
82     }
83
84     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
85
86     typedef GrGLSLXferProcessor INHERITED;
87 };
88
89 ///////////////////////////////////////////////////////////////////////////////
90
91 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
92     : fRegionOp(regionOp)
93     , fInvertCoverage(invertCoverage) {
94     this->initClassID<CoverageSetOpXP>();
95 }
96
97 CoverageSetOpXP::~CoverageSetOpXP() {
98 }
99
100 void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
101                                             GrProcessorKeyBuilder* b) const {
102     GLCoverageSetOpXP::GenKey(*this, caps, b);
103 }
104
105 GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
106     return new GLCoverageSetOpXP(*this);
107 }
108
109 GrXferProcessor::OptFlags
110 CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
111                                     bool doesStencilWrite,
112                                     GrColor* color,
113                                     const GrCaps& caps) const {
114     // We never look at the color input
115     return GrXferProcessor::kIgnoreColor_OptFlag; 
116 }
117
118 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
119     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
150 class ShaderCSOXferProcessor : public GrXferProcessor {
151 public:
152     ShaderCSOXferProcessor(const DstTexture* dstTexture,
153                            bool hasMixedSamples,
154                            SkXfermode::Mode xfermode,
155                            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
170 private:
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
193 class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
194 public:
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
202 private:
203     void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
204                                  GrGLSLXPFragmentBuilder* fragBuilder,
205                                  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
229 void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
230                                                    GrProcessorKeyBuilder* b) const {
231     GLShaderCSOXferProcessor::GenKey(*this, b);
232 }
233
234 GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
235     return new GLShaderCSOXferProcessor;
236 }
237
238 ///////////////////////////////////////////////////////////////////////////////
239 //
240 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
241     : fRegionOp(regionOp)
242     , fInvertCoverage(invertCoverage) {
243     this->initClassID<GrCoverageSetOpXPFactory>();
244 }
245
246 GrXPFactory* 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:
309             return nullptr;
310     }
311 }
312
313 GrXferProcessor*
314 GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
315                                                 const GrPipelineOptimizations& optimizations,
316                                                 bool hasMixedSamples,
317                                                 const DstTexture* dst) const {
318     // 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);
323         return nullptr;
324     }
325
326     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
327 }
328
329 void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
330                                                         InvariantBlendedColor* blendedColor) const {
331     blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
332     blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
333 }
334
335 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
336
337 const GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
338     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
339     bool invertCoverage = !d->fRenderTarget->hasMixedSamples() && d->fRandom->nextBool();
340     return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
341 }
342