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"
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"
19 class CoverageSetOpXP : public GrXferProcessor {
21 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
22 return new CoverageSetOpXP(regionOp, invertCoverage);
25 ~CoverageSetOpXP() override;
27 const char* name() const override { return "Coverage Set Op"; }
29 GrGLSLXferProcessor* createGLSLInstance() const override;
31 bool invertCoverage() const { return fInvertCoverage; }
34 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
36 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
37 bool doesStencilWrite,
39 const GrCaps& caps) const override;
41 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
43 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
45 bool onIsEqual(const GrXferProcessor& xpBase) const override {
46 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
47 return (fRegionOp == xp.fRegionOp &&
48 fInvertCoverage == xp.fInvertCoverage);
51 SkRegion::Op fRegionOp;
54 typedef GrXferProcessor INHERITED;
57 ///////////////////////////////////////////////////////////////////////////////
59 class GLCoverageSetOpXP : public GrGLSLXferProcessor {
61 GLCoverageSetOpXP(const GrProcessor&) {}
63 ~GLCoverageSetOpXP() override {}
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;
73 void emitOutputsForBlendState(const EmitArgs& args) override {
74 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
75 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
77 if (xp.invertCoverage()) {
78 fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
80 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
84 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
86 typedef GrGLSLXferProcessor INHERITED;
89 ///////////////////////////////////////////////////////////////////////////////
91 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
93 , fInvertCoverage(invertCoverage) {
94 this->initClassID<CoverageSetOpXP>();
97 CoverageSetOpXP::~CoverageSetOpXP() {
100 void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
101 GrProcessorKeyBuilder* b) const {
102 GLCoverageSetOpXP::GenKey(*this, caps, b);
105 GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
106 return new GLCoverageSetOpXP(*this);
109 GrXferProcessor::OptFlags
110 CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
111 bool doesStencilWrite,
113 const GrCaps& caps) const {
114 // We never look at the color input
115 return GrXferProcessor::kIgnoreColor_OptFlag;
118 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
120 case SkRegion::kReplace_Op:
121 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
122 blendInfo->fDstBlend = kZero_GrBlendCoeff;
124 case SkRegion::kIntersect_Op:
125 blendInfo->fSrcBlend = kDC_GrBlendCoeff;
126 blendInfo->fDstBlend = kZero_GrBlendCoeff;
128 case SkRegion::kUnion_Op:
129 blendInfo->fSrcBlend = kOne_GrBlendCoeff;
130 blendInfo->fDstBlend = kISC_GrBlendCoeff;
132 case SkRegion::kXOR_Op:
133 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
134 blendInfo->fDstBlend = kISC_GrBlendCoeff;
136 case SkRegion::kDifference_Op:
137 blendInfo->fSrcBlend = kZero_GrBlendCoeff;
138 blendInfo->fDstBlend = kISC_GrBlendCoeff;
140 case SkRegion::kReverseDifference_Op:
141 blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
142 blendInfo->fDstBlend = kZero_GrBlendCoeff;
145 blendInfo->fBlendConstant = 0;
148 ///////////////////////////////////////////////////////////////////////////////
150 class ShaderCSOXferProcessor : public GrXferProcessor {
152 ShaderCSOXferProcessor(const DstTexture* dstTexture,
153 bool hasMixedSamples,
154 SkXfermode::Mode xfermode,
155 SkRegion::Op regionOp,
157 : INHERITED(dstTexture, true, hasMixedSamples)
158 , fRegionOp(regionOp)
159 , fInvertCoverage(invertCoverage) {
160 this->initClassID<ShaderCSOXferProcessor>();
163 const char* name() const override { return "Coverage Set Op Shader"; }
165 GrGLSLXferProcessor* createGLSLInstance() const override;
167 SkRegion::Op regionOp() const { return fRegionOp; }
168 bool invertCoverage() const { return fInvertCoverage; }
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;
177 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
179 bool onIsEqual(const GrXferProcessor& xpBase) const override {
180 const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
181 return (fRegionOp == xp.fRegionOp &&
182 fInvertCoverage == xp.fInvertCoverage);
185 SkRegion::Op fRegionOp;
186 bool fInvertCoverage;
188 typedef GrXferProcessor INHERITED;
191 ///////////////////////////////////////////////////////////////////////////////
193 class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
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;
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>();
213 if (xp.invertCoverage()) {
214 fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
216 fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
219 GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
222 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
224 typedef GrGLSLXferProcessor INHERITED;
227 ///////////////////////////////////////////////////////////////////////////////
229 void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
230 GrProcessorKeyBuilder* b) const {
231 GLShaderCSOXferProcessor::GenKey(*this, b);
234 GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
235 return new GLShaderCSOXferProcessor;
238 ///////////////////////////////////////////////////////////////////////////////
240 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
241 : fRegionOp(regionOp)
242 , fInvertCoverage(invertCoverage) {
243 this->initClassID<GrCoverageSetOpXPFactory>();
246 GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
248 case SkRegion::kReplace_Op: {
249 if (invertCoverage) {
250 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
251 return SkRef(&gReplaceCDXPFI);
253 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
254 return SkRef(&gReplaceCDXPF);
258 case SkRegion::kIntersect_Op: {
259 if (invertCoverage) {
260 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
261 return SkRef(&gIntersectCDXPFI);
263 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
264 return SkRef(&gIntersectCDXPF);
268 case SkRegion::kUnion_Op: {
269 if (invertCoverage) {
270 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
271 return SkRef(&gUnionCDXPFI);
273 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
274 return SkRef(&gUnionCDXPF);
278 case SkRegion::kXOR_Op: {
279 if (invertCoverage) {
280 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
281 return SkRef(&gXORCDXPFI);
283 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
284 return SkRef(&gXORCDXPF);
288 case SkRegion::kDifference_Op: {
289 if (invertCoverage) {
290 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
291 return SkRef(&gDifferenceCDXPFI);
293 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
294 return SkRef(&gDifferenceCDXPF);
298 case SkRegion::kReverseDifference_Op: {
299 if (invertCoverage) {
300 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
301 return SkRef(&gRevDiffCDXPFI);
303 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
304 return SkRef(&gRevDiffCDXPF);
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) {
326 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
329 void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
330 InvariantBlendedColor* blendedColor) const {
331 blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
332 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
335 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
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);