blob: 02552b3bae8c7788a6c1b26a6304ee104e7141e5 [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"
10#include "GrColor.h"
11#include "GrDrawTargetCaps.h"
egdaniel87509242014-12-17 13:37:13 -080012#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
egdaniel41d4f092015-02-09 07:51:00 -080018class CoverageSetOpXP : public GrXferProcessor {
egdaniel87509242014-12-17 13:37:13 -080019public:
egdaniel41d4f092015-02-09 07:51:00 -080020 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
21 return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
22 }
egdaniel87509242014-12-17 13:37:13 -080023
mtklein36352bf2015-03-25 18:17:31 -070024 ~CoverageSetOpXP() override;
egdaniel41d4f092015-02-09 07:51:00 -080025
mtklein36352bf2015-03-25 18:17:31 -070026 const char* name() const override { return "Coverage Set Op"; }
egdaniel41d4f092015-02-09 07:51:00 -080027
mtklein36352bf2015-03-25 18:17:31 -070028 GrGLXferProcessor* createGLInstance() const override;
egdaniel41d4f092015-02-09 07:51:00 -080029
mtklein36352bf2015-03-25 18:17:31 -070030 bool hasSecondaryOutput() const override { return false; }
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
egdanielc19cdc22015-05-10 08:45:18 -070037 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
38 const GrProcOptInfo& coveragePOI,
39 bool doesStencilWrite,
40 GrColor* color,
41 const GrDrawTargetCaps& caps) override;
42
jvanverthcfc18862015-04-28 08:48:20 -070043 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
egdaniel41d4f092015-02-09 07:51:00 -080044
cdaltonf4f2b442015-04-23 09:40:23 -070045 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
46
mtklein36352bf2015-03-25 18:17:31 -070047 bool onIsEqual(const GrXferProcessor& xpBase) const override {
egdaniel41d4f092015-02-09 07:51:00 -080048 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
61class GLCoverageSetOpXP : public GrGLXferProcessor {
62public:
63 GLCoverageSetOpXP(const GrProcessor&) {}
64
mtklein36352bf2015-03-25 18:17:31 -070065 ~GLCoverageSetOpXP() override {}
egdaniel87509242014-12-17 13:37:13 -080066
jvanverthcfc18862015-04-28 08:48:20 -070067 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
bsalomon50785a32015-02-06 07:02:37 -080068 GrProcessorKeyBuilder* b) {
egdaniel41d4f092015-02-09 07:51:00 -080069 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
bsalomon50785a32015-02-06 07:02:37 -080070 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
71 b->add32(key);
72 };
73
74private:
mtklein36352bf2015-03-25 18:17:31 -070075 void onEmitCode(const EmitArgs& args) override {
egdaniel41d4f092015-02-09 07:51:00 -080076 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
egdaniel29bee0f2015-04-29 11:54:42 -070077 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
egdaniel87509242014-12-17 13:37:13 -080078
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
mtklein36352bf2015-03-25 18:17:31 -070086 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {};
egdaniel87509242014-12-17 13:37:13 -080087
egdaniel87509242014-12-17 13:37:13 -080088 typedef GrGLXferProcessor INHERITED;
89};
90
91///////////////////////////////////////////////////////////////////////////////
92
egdaniel41d4f092015-02-09 07:51:00 -080093CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
egdaniel87509242014-12-17 13:37:13 -080094 : fRegionOp(regionOp)
95 , fInvertCoverage(invertCoverage) {
egdaniel41d4f092015-02-09 07:51:00 -080096 this->initClassID<CoverageSetOpXP>();
egdaniel87509242014-12-17 13:37:13 -080097}
98
egdaniel41d4f092015-02-09 07:51:00 -080099CoverageSetOpXP::~CoverageSetOpXP() {
egdaniel87509242014-12-17 13:37:13 -0800100}
101
jvanverthcfc18862015-04-28 08:48:20 -0700102void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel41d4f092015-02-09 07:51:00 -0800103 GLCoverageSetOpXP::GenKey(*this, caps, b);
egdaniel87509242014-12-17 13:37:13 -0800104}
105
egdaniel41d4f092015-02-09 07:51:00 -0800106GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
107 return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
egdaniel87509242014-12-17 13:37:13 -0800108}
109
110GrXferProcessor::OptFlags
egdanielc19cdc22015-05-10 08:45:18 -0700111CoverageSetOpXP::onGetOptimizations(const GrProcOptInfo& colorPOI,
112 const GrProcOptInfo& coveragePOI,
113 bool doesStencilWrite,
114 GrColor* color,
115 const GrDrawTargetCaps& caps) {
egdaniel87509242014-12-17 13:37:13 -0800116 // We never look at the color input
117 return GrXferProcessor::kIgnoreColor_OptFlag;
118}
119
cdaltonf4f2b442015-04-23 09:40:23 -0700120void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
egdaniel87509242014-12-17 13:37:13 -0800121 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
152GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
153 : fRegionOp(regionOp)
154 , fInvertCoverage(invertCoverage) {
155 this->initClassID<GrCoverageSetOpXPFactory>();
156}
157
158GrXPFactory* 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
bsalomon50785a32015-02-06 07:02:37 -0800225GrXferProcessor*
egdaniel3ad65702015-02-17 11:15:47 -0800226GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
227 const GrProcOptInfo& colorPOI,
bsalomon50785a32015-02-06 07:02:37 -0800228 const GrProcOptInfo& covPOI,
229 const GrDeviceCoordTexture* dstCopy) const {
egdaniel41d4f092015-02-09 07:51:00 -0800230 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
egdaniel87509242014-12-17 13:37:13 -0800231}
232
egdaniel9e4ecdc2014-12-18 12:44:55 -0800233void GrCoverageSetOpXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
234 const GrProcOptInfo& coveragePOI,
egdaniel9e4ecdc2014-12-18 12:44:55 -0800235 GrXPFactory::InvariantOutput* output) const {
236 if (SkRegion::kReplace_Op == fRegionOp) {
237 if (coveragePOI.isSolidWhite()) {
238 output->fBlendedColor = GrColor_WHITE;
239 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
egdaniel87509242014-12-17 13:37:13 -0800240 } else {
egdaniel9e4ecdc2014-12-18 12:44:55 -0800241 output->fBlendedColorFlags = 0;
egdaniel87509242014-12-17 13:37:13 -0800242 }
egdaniel9e4ecdc2014-12-18 12:44:55 -0800243
egdaniel71e236c2015-01-20 06:34:51 -0800244 output->fWillBlendWithDst = false;
egdaniel9e4ecdc2014-12-18 12:44:55 -0800245 } else {
246 output->fBlendedColorFlags = 0;
247 output->fWillBlendWithDst = true;
egdaniel87509242014-12-17 13:37:13 -0800248 }
egdaniel87509242014-12-17 13:37:13 -0800249}
250
egdaniel87509242014-12-17 13:37:13 -0800251GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
252
253GrXPFactory* 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