1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrPipelineBuilder.h"
9 
10 #include "GrBatch.h"
11 #include "GrBlend.h"
12 #include "GrPaint.h"
13 #include "GrPipeline.h"
14 #include "GrProcOptInfo.h"
15 #include "GrXferProcessor.h"
16 #include "effects/GrPorterDuffXferProcessor.h"
17 
GrPipelineBuilder()18 GrPipelineBuilder::GrPipelineBuilder()
19     : fFlags(0x0)
20     , fDrawFace(kBoth_DrawFace)
21     , fColorProcInfoValid(false)
22     , fCoverageProcInfoValid(false)
23     , fColorCache(GrColor_ILLEGAL)
24     , fCoverageCache(GrColor_ILLEGAL) {
25     SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
26 }
27 
operator =(const GrPipelineBuilder & that)28 GrPipelineBuilder& GrPipelineBuilder::operator=(const GrPipelineBuilder& that) {
29     fRenderTarget.reset(SkSafeRef(that.fRenderTarget.get()));
30     fFlags = that.fFlags;
31     fStencilSettings = that.fStencilSettings;
32     fDrawFace = that.fDrawFace;
33     fXPFactory.reset(SkRef(that.getXPFactory()));
34     fColorStages = that.fColorStages;
35     fCoverageStages = that.fCoverageStages;
36     fClip = that.fClip;
37 
38     fColorProcInfoValid = that.fColorProcInfoValid;
39     fCoverageProcInfoValid = that.fCoverageProcInfoValid;
40     fColorCache = that.fColorCache;
41     fCoverageCache = that.fCoverageCache;
42     if (fColorProcInfoValid) {
43         fColorProcInfo = that.fColorProcInfo;
44     }
45     if (fCoverageProcInfoValid) {
46         fCoverageProcInfo = that.fCoverageProcInfo;
47     }
48     return *this;
49 }
50 
setFromPaint(const GrPaint & paint,GrRenderTarget * rt,const GrClip & clip)51 void GrPipelineBuilder::setFromPaint(const GrPaint& paint, GrRenderTarget* rt, const GrClip& clip) {
52     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numFragmentStages());
53 
54     fColorStages.reset();
55     fCoverageStages.reset();
56 
57     for (int i = 0; i < paint.numColorStages(); ++i) {
58         fColorStages.push_back(paint.getColorStage(i));
59     }
60 
61     for (int i = 0; i < paint.numCoverageStages(); ++i) {
62         fCoverageStages.push_back(paint.getCoverageStage(i));
63     }
64 
65     fXPFactory.reset(SkRef(paint.getXPFactory()));
66 
67     this->setRenderTarget(rt);
68 
69     // These have no equivalent in GrPaint, set them to defaults
70     fDrawFace = kBoth_DrawFace;
71     fStencilSettings.setDisabled();
72     fFlags = 0;
73 
74     fClip = clip;
75 
76     this->setState(GrPipelineBuilder::kDither_Flag, paint.isDither());
77     this->setState(GrPipelineBuilder::kHWAntialias_Flag,
78                    rt->isMultisampled() && paint.isAntiAlias());
79 
80     fColorProcInfoValid = false;
81     fCoverageProcInfoValid = false;
82 
83     fColorCache = GrColor_ILLEGAL;
84     fCoverageCache = GrColor_ILLEGAL;
85 }
86 
87 //////////////////////////////////////////////////////////////////////////////s
88 
willXPNeedDstCopy(const GrDrawTargetCaps & caps,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI) const89 bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps,
90                                           const GrProcOptInfo& colorPOI,
91                                           const GrProcOptInfo& coveragePOI) const {
92     return this->getXPFactory()->willNeedDstCopy(caps, colorPOI, coveragePOI);
93 }
94 
set(GrPipelineBuilder * pipelineBuilder)95 void GrPipelineBuilder::AutoRestoreFragmentProcessors::set(GrPipelineBuilder* pipelineBuilder) {
96     if (fPipelineBuilder) {
97         int m = fPipelineBuilder->numColorFragmentStages() - fColorEffectCnt;
98         SkASSERT(m >= 0);
99         fPipelineBuilder->fColorStages.pop_back_n(m);
100 
101         int n = fPipelineBuilder->numCoverageFragmentStages() - fCoverageEffectCnt;
102         SkASSERT(n >= 0);
103         fPipelineBuilder->fCoverageStages.pop_back_n(n);
104         if (m + n > 0) {
105             fPipelineBuilder->fColorProcInfoValid = false;
106             fPipelineBuilder->fCoverageProcInfoValid = false;
107         }
108         SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
109     }
110     fPipelineBuilder = pipelineBuilder;
111     if (NULL != pipelineBuilder) {
112         fColorEffectCnt = pipelineBuilder->numColorFragmentStages();
113         fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentStages();
114         SkDEBUGCODE(++pipelineBuilder->fBlockEffectRemovalCnt;)
115     }
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
119 
~GrPipelineBuilder()120 GrPipelineBuilder::~GrPipelineBuilder() {
121     SkASSERT(0 == fBlockEffectRemovalCnt);
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 
willBlendWithDst(const GrPrimitiveProcessor * pp) const126 bool GrPipelineBuilder::willBlendWithDst(const GrPrimitiveProcessor* pp) const {
127     this->calcColorInvariantOutput(pp);
128     this->calcCoverageInvariantOutput(pp);
129 
130     GrXPFactory::InvariantOutput output;
131     fXPFactory->getInvariantOutput(fColorProcInfo, fCoverageProcInfo, &output);
132     return output.fWillBlendWithDst;
133 }
134 
calcColorInvariantOutput(const GrPrimitiveProcessor * pp) const135 void GrPipelineBuilder::calcColorInvariantOutput(const GrPrimitiveProcessor* pp) const {
136     fColorProcInfo.calcColorWithPrimProc(pp, fColorStages.begin(), this->numColorFragmentStages());
137     fColorProcInfoValid = false;
138 
139 }
140 
calcCoverageInvariantOutput(const GrPrimitiveProcessor * pp) const141 void GrPipelineBuilder::calcCoverageInvariantOutput(const GrPrimitiveProcessor* pp) const {
142     fCoverageProcInfo.calcCoverageWithPrimProc(pp, fCoverageStages.begin(),
143                                                this->numCoverageFragmentStages());
144     fCoverageProcInfoValid = false;
145 }
146 
calcColorInvariantOutput(const GrBatch * batch) const147 void GrPipelineBuilder::calcColorInvariantOutput(const GrBatch* batch) const {
148     fColorProcInfo.calcColorWithBatch(batch, fColorStages.begin(), this->numColorFragmentStages());
149     fColorProcInfoValid = false;
150 }
151 
calcCoverageInvariantOutput(const GrBatch * batch) const152 void GrPipelineBuilder::calcCoverageInvariantOutput(const GrBatch* batch) const {
153     fCoverageProcInfo.calcCoverageWithBatch(batch, fCoverageStages.begin(),
154                                             this->numCoverageFragmentStages());
155     fCoverageProcInfoValid = false;
156 }
157 
158 
calcColorInvariantOutput(GrColor color) const159 void GrPipelineBuilder::calcColorInvariantOutput(GrColor color) const {
160     if (!fColorProcInfoValid || color != fColorCache) {
161         GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
162         fColorProcInfo.calcWithInitialValues(fColorStages.begin(),this->numColorFragmentStages(),
163                                              color, flags, false);
164         fColorProcInfoValid = true;
165         fColorCache = color;
166     }
167 }
168 
calcCoverageInvariantOutput(GrColor coverage) const169 void GrPipelineBuilder::calcCoverageInvariantOutput(GrColor coverage) const {
170     if (!fCoverageProcInfoValid || coverage != fCoverageCache) {
171         GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
172         fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(),
173                                                 this->numCoverageFragmentStages(), coverage, flags,
174                                                 true);
175         fCoverageProcInfoValid = true;
176         fCoverageCache = coverage;
177     }
178 }
179