6f49a1d50437b2a00d519dd1795221ea349ea358
[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 "GrColor.h"
11 #include "GrDrawTargetCaps.h"
12 #include "GrProcessor.h"
13 #include "GrProcOptInfo.h"
14 #include "gl/GrGLXferProcessor.h"
15 #include "gl/builders/GrGLFragmentShaderBuilder.h"
16 #include "gl/builders/GrGLProgramBuilder.h"
17
18 class CoverageSetOpXP : public GrXferProcessor {
19 public:
20     static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
21         return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
22     }
23
24     ~CoverageSetOpXP() SK_OVERRIDE;
25
26     const char* name() const SK_OVERRIDE { return "Coverage Set Op"; }
27
28     GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
29
30     bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
31
32     GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
33                                                const GrProcOptInfo& coveragePOI,
34                                                bool doesStencilWrite,
35                                                GrColor* color,
36                                                const GrDrawTargetCaps& caps) SK_OVERRIDE;
37
38     void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE;
39
40     bool invertCoverage() const { return fInvertCoverage; }
41
42 private:
43     CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
44
45     void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
46
47     bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
48         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
49         return (fRegionOp == xp.fRegionOp &&
50                 fInvertCoverage == xp.fInvertCoverage);
51     }
52
53     SkRegion::Op fRegionOp;
54     bool         fInvertCoverage;
55
56     typedef GrXferProcessor INHERITED;
57 };
58
59 ///////////////////////////////////////////////////////////////////////////////
60
61 class GLCoverageSetOpXP : public GrGLXferProcessor {
62 public:
63     GLCoverageSetOpXP(const GrProcessor&) {}
64
65     ~GLCoverageSetOpXP() SK_OVERRIDE {}
66
67     static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
68                        GrProcessorKeyBuilder* b) {
69         const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
70         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
71         b->add32(key);
72     };
73
74 private:
75     void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
76         const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
77         GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
78
79         if (xp.invertCoverage()) {
80             fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
81         } else {
82             fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
83         }
84     }
85
86     void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
87
88     typedef GrGLXferProcessor INHERITED;
89 };
90
91 ///////////////////////////////////////////////////////////////////////////////
92
93 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
94     : fRegionOp(regionOp)
95     , fInvertCoverage(invertCoverage) {
96     this->initClassID<CoverageSetOpXP>();
97 }
98
99 CoverageSetOpXP::~CoverageSetOpXP() {
100 }
101
102 void CoverageSetOpXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
103     GLCoverageSetOpXP::GenKey(*this, caps, b);
104 }
105
106 GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
107     return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
108 }
109
110 GrXferProcessor::OptFlags
111 CoverageSetOpXP::getOptimizations(const GrProcOptInfo& colorPOI,
112                                   const GrProcOptInfo& coveragePOI,
113                                   bool doesStencilWrite,
114                                   GrColor* color,
115                                   const GrDrawTargetCaps& caps) {
116     // We never look at the color input
117     return GrXferProcessor::kIgnoreColor_OptFlag; 
118 }
119
120 void CoverageSetOpXP::getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
121     switch (fRegionOp) {
122         case SkRegion::kReplace_Op:
123             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
124             blendInfo->fDstBlend = kZero_GrBlendCoeff;
125             break;
126         case SkRegion::kIntersect_Op:
127             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
128             blendInfo->fDstBlend = kZero_GrBlendCoeff;
129             break;
130         case SkRegion::kUnion_Op:
131             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
132             blendInfo->fDstBlend = kISC_GrBlendCoeff;
133             break;
134         case SkRegion::kXOR_Op:
135             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
136             blendInfo->fDstBlend = kISC_GrBlendCoeff;
137             break;
138         case SkRegion::kDifference_Op:
139             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
140             blendInfo->fDstBlend = kISC_GrBlendCoeff;
141             break;
142         case SkRegion::kReverseDifference_Op:
143             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
144             blendInfo->fDstBlend = kZero_GrBlendCoeff;
145             break;
146     }
147     blendInfo->fBlendConstant = 0;
148 }
149
150 ///////////////////////////////////////////////////////////////////////////////
151
152 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
153     : fRegionOp(regionOp)
154     , fInvertCoverage(invertCoverage) {
155     this->initClassID<GrCoverageSetOpXPFactory>();
156 }
157
158 GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
159     switch (regionOp) {
160         case SkRegion::kReplace_Op: {
161             if (invertCoverage) {
162                 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
163                 return SkRef(&gReplaceCDXPFI);
164             } else {
165                 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
166                 return SkRef(&gReplaceCDXPF);
167             }
168             break;
169         }
170         case SkRegion::kIntersect_Op: {
171             if (invertCoverage) {
172                 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
173                 return SkRef(&gIntersectCDXPFI);
174             } else {
175                 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
176                 return SkRef(&gIntersectCDXPF);
177             }
178             break;
179         }
180         case SkRegion::kUnion_Op: {
181             if (invertCoverage) {
182                 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
183                 return SkRef(&gUnionCDXPFI);
184             } else {
185                 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
186                 return SkRef(&gUnionCDXPF);
187             }
188             break;
189         }
190         case SkRegion::kXOR_Op: {
191             if (invertCoverage) {
192                 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
193                 return SkRef(&gXORCDXPFI);
194             } else {
195                 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
196                 return SkRef(&gXORCDXPF);
197             }
198             break;
199         }
200         case SkRegion::kDifference_Op: {
201             if (invertCoverage) {
202                 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
203                 return SkRef(&gDifferenceCDXPFI);
204             } else {
205                 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
206                 return SkRef(&gDifferenceCDXPF);
207             }
208             break;
209         }
210         case SkRegion::kReverseDifference_Op: {
211             if (invertCoverage) {
212                 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
213                 return SkRef(&gRevDiffCDXPFI);
214             } else {
215                 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
216                 return SkRef(&gRevDiffCDXPF);
217             }
218             break;
219         }
220         default:
221             return NULL;
222     }
223 }
224
225 GrXferProcessor*
226 GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
227                                                 const GrProcOptInfo& colorPOI,
228                                                 const GrProcOptInfo& covPOI,
229                                                 const GrDeviceCoordTexture* dstCopy) const {
230     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
231 }
232
233 void GrCoverageSetOpXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
234                                                   const GrProcOptInfo& coveragePOI,
235                                                   GrXPFactory::InvariantOutput* output) const {
236     if (SkRegion::kReplace_Op == fRegionOp) {
237         if (coveragePOI.isSolidWhite()) {
238             output->fBlendedColor = GrColor_WHITE;
239             output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
240         } else {
241             output->fBlendedColorFlags = 0;
242         }
243
244         output->fWillBlendWithDst = false;
245     } else {
246         output->fBlendedColorFlags = 0;
247         output->fWillBlendWithDst = true;
248     }
249 }
250
251 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
252
253 GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random,
254                                                   GrContext*,
255                                                   const GrDrawTargetCaps&,
256                                                   GrTexture*[]) {
257     SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1));
258     bool invertCoverage = random->nextBool();
259     return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
260 }
261