3 * Copyright 2014 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
9 #include "effects/GrCoverageSetOpXP.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"
18 class CoverageSetOpXP : public GrXferProcessor {
20 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
21 return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
24 ~CoverageSetOpXP() SK_OVERRIDE;
26 const char* name() const SK_OVERRIDE { return "Coverage Set Op"; }
28 GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
30 bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
32 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
33 const GrProcOptInfo& coveragePOI,
34 bool doesStencilWrite,
36 const GrDrawTargetCaps& caps) SK_OVERRIDE;
38 void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE;
40 bool invertCoverage() const { return fInvertCoverage; }
43 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
45 void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
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);
53 SkRegion::Op fRegionOp;
56 typedef GrXferProcessor INHERITED;
59 ///////////////////////////////////////////////////////////////////////////////
61 class GLCoverageSetOpXP : public GrGLXferProcessor {
63 GLCoverageSetOpXP(const GrProcessor&) {}
65 ~GLCoverageSetOpXP() SK_OVERRIDE {}
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;
75 void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
76 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
77 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
79 if (xp.invertCoverage()) {
80 fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
82 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
86 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
88 typedef GrGLXferProcessor INHERITED;
91 ///////////////////////////////////////////////////////////////////////////////
93 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
95 , fInvertCoverage(invertCoverage) {
96 this->initClassID<CoverageSetOpXP>();
99 CoverageSetOpXP::~CoverageSetOpXP() {
102 void CoverageSetOpXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
103 GLCoverageSetOpXP::GenKey(*this, caps, b);
106 GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
107 return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
110 GrXferProcessor::OptFlags
111 CoverageSetOpXP::getOptimizations(const GrProcOptInfo& colorPOI,
112 const GrProcOptInfo& coveragePOI,
113 bool doesStencilWrite,
115 const GrDrawTargetCaps& caps) {
116 // We never look at the color input
117 return GrXferProcessor::kIgnoreColor_OptFlag;
120 void CoverageSetOpXP::getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
122 case SkRegion::kReplace_Op:
123 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
124 blendInfo->fDstBlend = kZero_GrBlendCoeff;
126 case SkRegion::kIntersect_Op:
127 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
128 blendInfo->fDstBlend = kZero_GrBlendCoeff;
130 case SkRegion::kUnion_Op:
131 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
132 blendInfo->fDstBlend = kISC_GrBlendCoeff;
134 case SkRegion::kXOR_Op:
135 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
136 blendInfo->fDstBlend = kISC_GrBlendCoeff;
138 case SkRegion::kDifference_Op:
139 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
140 blendInfo->fDstBlend = kISC_GrBlendCoeff;
142 case SkRegion::kReverseDifference_Op:
143 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
144 blendInfo->fDstBlend = kZero_GrBlendCoeff;
147 blendInfo->fBlendConstant = 0;
150 ///////////////////////////////////////////////////////////////////////////////
152 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
153 : fRegionOp(regionOp)
154 , fInvertCoverage(invertCoverage) {
155 this->initClassID<GrCoverageSetOpXPFactory>();
158 GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
160 case SkRegion::kReplace_Op: {
161 if (invertCoverage) {
162 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
163 return SkRef(&gReplaceCDXPFI);
165 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
166 return SkRef(&gReplaceCDXPF);
170 case SkRegion::kIntersect_Op: {
171 if (invertCoverage) {
172 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
173 return SkRef(&gIntersectCDXPFI);
175 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
176 return SkRef(&gIntersectCDXPF);
180 case SkRegion::kUnion_Op: {
181 if (invertCoverage) {
182 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
183 return SkRef(&gUnionCDXPFI);
185 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
186 return SkRef(&gUnionCDXPF);
190 case SkRegion::kXOR_Op: {
191 if (invertCoverage) {
192 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
193 return SkRef(&gXORCDXPFI);
195 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
196 return SkRef(&gXORCDXPF);
200 case SkRegion::kDifference_Op: {
201 if (invertCoverage) {
202 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
203 return SkRef(&gDifferenceCDXPFI);
205 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
206 return SkRef(&gDifferenceCDXPF);
210 case SkRegion::kReverseDifference_Op: {
211 if (invertCoverage) {
212 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
213 return SkRef(&gRevDiffCDXPFI);
215 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
216 return SkRef(&gRevDiffCDXPF);
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);
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;
241 output->fBlendedColorFlags = 0;
244 output->fWillBlendWithDst = false;
246 output->fBlendedColorFlags = 0;
247 output->fWillBlendWithDst = true;
251 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
253 GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random,
255 const GrDrawTargetCaps&,
257 SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1));
258 bool invertCoverage = random->nextBool();
259 return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);