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:
Create(SkRegion::Op regionOp,bool invertCoverage)20 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
21 return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
22 }
23
24 ~CoverageSetOpXP() override;
25
name() const26 const char* name() const override { return "Coverage Set Op"; }
27
28 GrGLXferProcessor* createGLInstance() const override;
29
hasSecondaryOutput() const30 bool hasSecondaryOutput() const override { return false; }
31
invertCoverage() const32 bool invertCoverage() const { return fInvertCoverage; }
33
34 private:
35 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
36
37 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
38 const GrProcOptInfo& coveragePOI,
39 bool doesStencilWrite,
40 GrColor* color,
41 const GrDrawTargetCaps& caps) override;
42
43 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
44
45 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
46
onIsEqual(const GrXferProcessor & xpBase) const47 bool onIsEqual(const GrXferProcessor& xpBase) const 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:
GLCoverageSetOpXP(const GrProcessor &)63 GLCoverageSetOpXP(const GrProcessor&) {}
64
~GLCoverageSetOpXP()65 ~GLCoverageSetOpXP() override {}
66
GenKey(const GrProcessor & processor,const GrGLSLCaps & caps,GrProcessorKeyBuilder * b)67 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& 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:
onEmitCode(const EmitArgs & args)75 void onEmitCode(const EmitArgs& args) override {
76 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
77 GrGLXPFragmentBuilder* 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
onSetData(const GrGLProgramDataManager &,const GrXferProcessor &)86 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {};
87
88 typedef GrGLXferProcessor INHERITED;
89 };
90
91 ///////////////////////////////////////////////////////////////////////////////
92
CoverageSetOpXP(SkRegion::Op regionOp,bool invertCoverage)93 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
94 : fRegionOp(regionOp)
95 , fInvertCoverage(invertCoverage) {
96 this->initClassID<CoverageSetOpXP>();
97 }
98
~CoverageSetOpXP()99 CoverageSetOpXP::~CoverageSetOpXP() {
100 }
101
onGetGLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const102 void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
103 GLCoverageSetOpXP::GenKey(*this, caps, b);
104 }
105
createGLInstance() const106 GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
107 return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
108 }
109
110 GrXferProcessor::OptFlags
onGetOptimizations(const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,bool doesStencilWrite,GrColor * color,const GrDrawTargetCaps & caps)111 CoverageSetOpXP::onGetOptimizations(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
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const120 void CoverageSetOpXP::onGetBlendInfo(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
GrCoverageSetOpXPFactory(SkRegion::Op regionOp,bool invertCoverage)152 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
153 : fRegionOp(regionOp)
154 , fInvertCoverage(invertCoverage) {
155 this->initClassID<GrCoverageSetOpXPFactory>();
156 }
157
Create(SkRegion::Op regionOp,bool invertCoverage)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*
onCreateXferProcessor(const GrDrawTargetCaps & caps,const GrProcOptInfo & colorPOI,const GrProcOptInfo & covPOI,const GrDeviceCoordTexture * dstCopy) const226 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
getInvariantOutput(const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,GrXPFactory::InvariantOutput * output) const233 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
TestCreate(SkRandom * random,GrContext *,const GrDrawTargetCaps &,GrTexture * [])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
262