blob: 70209e17593ccb9cf5b29c28c422b2df6e38b191 [file] [log] [blame]
egdaniel3658f382014-09-15 07:01:59 -07001/*
2 * Copyright 2014 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 "GrOptDrawState.h"
9
10#include "GrDrawState.h"
egdanielc0648242014-09-22 13:17:02 -070011#include "GrDrawTargetCaps.h"
12#include "GrGpu.h"
egdaniel3658f382014-09-15 07:01:59 -070013
egdaniel170f90b2014-09-16 12:54:40 -070014GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
15 BlendOptFlags blendOptFlags,
16 GrBlendCoeff optSrcCoeff,
egdanielc0648242014-09-22 13:17:02 -070017 GrBlendCoeff optDstCoeff,
18 const GrDrawTargetCaps& caps) : INHERITED(drawState) {
egdaniel3658f382014-09-15 07:01:59 -070019 fColor = drawState.getColor();
20 fCoverage = drawState.getCoverage();
21 fViewMatrix = drawState.getViewMatrix();
22 fBlendConstant = drawState.getBlendConstant();
23 fFlagBits = drawState.getFlagBits();
24 fVAPtr = drawState.getVertexAttribs();
25 fVACount = drawState.getVertexAttribCount();
26 fVAStride = drawState.getVertexStride();
27 fStencilSettings = drawState.getStencil();
28 fDrawFace = drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070029 fBlendOptFlags = blendOptFlags;
30 fSrcBlend = optSrcCoeff;
31 fDstBlend = optDstCoeff;
egdaniel3658f382014-09-15 07:01:59 -070032
33 memcpy(fFixedFunctionVertexAttribIndices,
34 drawState.getFixedFunctionVertexAttribIndices(),
35 sizeof(fFixedFunctionVertexAttribIndices));
36
egdaniel170f90b2014-09-16 12:54:40 -070037
egdaniel3658f382014-09-15 07:01:59 -070038 fInputColorIsUsed = true;
39 fInputCoverageIsUsed = true;
40
41 if (drawState.hasGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -070042 fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*drawState.getGeometryProcessor())));
egdaniel3658f382014-09-15 07:01:59 -070043 } else {
44 fGeometryProcessor.reset(NULL);
45 }
46
47 this->copyEffectiveColorStages(drawState);
48 this->copyEffectiveCoverageStages(drawState);
egdaniel170f90b2014-09-16 12:54:40 -070049 this->adjustFromBlendOpts();
egdaniela7dc0a82014-09-17 08:25:05 -070050 this->getStageStats();
egdanielc0648242014-09-22 13:17:02 -070051 this->setOutputStateInfo(caps);
egdaniel3658f382014-09-15 07:01:59 -070052};
53
egdanielc0648242014-09-22 13:17:02 -070054void GrOptDrawState::setOutputStateInfo(const GrDrawTargetCaps& caps) {
55 // Set this default and then possibly change our mind if there is coverage.
56 fPrimaryOutputType = kModulate_PrimaryOutputType;
57 fSecondaryOutputType = kNone_SecondaryOutputType;
58
59 // If we do have coverage determine whether it matters.
60 bool separateCoverageFromColor = this->hasGeometryProcessor();
61 if (!this->isCoverageDrawing() &&
62 (this->numCoverageStages() > 0 ||
63 this->hasGeometryProcessor() ||
64 this->hasCoverageVertexAttribute())) {
65
66 if (caps.dualSourceBlendingSupport()) {
67 if (kZero_GrBlendCoeff == fDstBlend) {
68 // write the coverage value to second color
69 fSecondaryOutputType = kCoverage_SecondaryOutputType;
70 separateCoverageFromColor = true;
71 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
72 } else if (kSA_GrBlendCoeff == fDstBlend) {
73 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
74 fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
75 separateCoverageFromColor = true;
76 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
77 } else if (kSC_GrBlendCoeff == fDstBlend) {
78 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
79 fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
80 separateCoverageFromColor = true;
81 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
82 }
83 } else if (fReadsDst &&
84 kOne_GrBlendCoeff == fSrcBlend &&
85 kZero_GrBlendCoeff == fDstBlend) {
86 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType;
87 separateCoverageFromColor = true;
88 }
89 }
90
91 // TODO: Once we have flag to know if we only multiply on stages, only push coverage into color
92 // stages if everything is multipy
93 if (!separateCoverageFromColor) {
94 for (int s = 0; s < this->numCoverageStages(); ++s) {
95 fColorStages.push_back(this->getCoverageStage(s));
96 }
97 fCoverageStages.reset();
98 }
99}
100
egdaniel170f90b2014-09-16 12:54:40 -0700101void GrOptDrawState::adjustFromBlendOpts() {
102
103 switch (fBlendOptFlags) {
104 case kNone_BlendOpt:
105 case kSkipDraw_BlendOptFlag:
106 break;
107 case kCoverageAsAlpha_BlendOptFlag:
108 fFlagBits |= kCoverageDrawing_StateBit;
109 break;
110 case kEmitCoverage_BlendOptFlag:
111 fColor = 0xffffffff;
112 fInputColorIsUsed = true;
113 fColorStages.reset();
114 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
115 break;
116 case kEmitTransBlack_BlendOptFlag:
117 fColor = 0;
118 fCoverage = 0xff;
119 fInputColorIsUsed = true;
120 fInputCoverageIsUsed = true;
121 fColorStages.reset();
122 fCoverageStages.reset();
123 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
124 0x1 << kCoverage_GrVertexAttribBinding);
125 break;
126 default:
127 SkFAIL("Unknown BlendOptFlag");
128
129 }
130}
131
egdaniel3658f382014-09-15 07:01:59 -0700132void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
133 int numToRemove = 0;
134 uint8_t maskCheck = 0x1;
135 // Count the number of vertex attributes that we will actually remove
136 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
137 if ((maskCheck & removeVAFlag) && -1 != fFixedFunctionVertexAttribIndices[i]) {
138 ++numToRemove;
139 }
140 maskCheck <<= 1;
141 }
egdaniel170f90b2014-09-16 12:54:40 -0700142
egdaniel3658f382014-09-15 07:01:59 -0700143 fOptVA.reset(fVACount - numToRemove);
144
145 GrVertexAttrib* dst = fOptVA.get();
146 const GrVertexAttrib* src = fVAPtr;
147
148 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
149 const GrVertexAttrib& currAttrib = *src;
150 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
151 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
152 if (maskCheck & removeVAFlag) {
153 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
154 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
155 continue;
156 }
egdaniel170f90b2014-09-16 12:54:40 -0700157 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700158 }
159 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700160 ++newIdx;
161 ++dst;
162 }
163 fVACount -= numToRemove;
164 fVAPtr = fOptVA.get();
165}
166
167void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
168 int firstColorStage = 0;
169
170 // Set up color and flags for ConstantColorComponent checks
171 GrColor color;
172 uint32_t validComponentFlags;
173 if (!this->hasColorVertexAttribute()) {
174 color = ds.getColor();
175 validComponentFlags = kRGBA_GrColorComponentFlags;
176 } else {
177 if (ds.vertexColorsAreOpaque()) {
178 color = 0xFF << GrColor_SHIFT_A;
179 validComponentFlags = kA_GrColorComponentFlag;
180 } else {
181 validComponentFlags = 0;
182 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
183 }
184 }
185
186 for (int i = 0; i < ds.numColorStages(); ++i) {
joshualittb0a8a372014-09-23 09:50:21 -0700187 const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
188 if (!fp->willUseInputColor()) {
egdaniel3658f382014-09-15 07:01:59 -0700189 firstColorStage = i;
190 fInputColorIsUsed = false;
191 }
joshualittb0a8a372014-09-23 09:50:21 -0700192 fp->getConstantColorComponents(&color, &validComponentFlags);
egdaniel3658f382014-09-15 07:01:59 -0700193 if (kRGBA_GrColorComponentFlags == validComponentFlags) {
194 firstColorStage = i + 1;
195 fColor = color;
196 fInputColorIsUsed = true;
197 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
198 }
199 }
200 if (firstColorStage < ds.numColorStages()) {
201 fColorStages.reset(&ds.getColorStage(firstColorStage),
202 ds.numColorStages() - firstColorStage);
203 } else {
204 fColorStages.reset();
205 }
206}
207
208void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
209 int firstCoverageStage = 0;
210
211 // We do not try to optimize out constantColor coverage effects here. It is extremely rare
212 // to have a coverage effect that returns a constant value for all four channels. Thus we
213 // save having to make extra virtual calls by not checking for it.
214
215 // Don't do any optimizations on coverage stages. It should not be the case where we do not use
216 // input coverage in an effect
217#ifdef OptCoverageStages
218 for (int i = 0; i < ds.numCoverageStages(); ++i) {
joshualittb0a8a372014-09-23 09:50:21 -0700219 const GrProcessor* processor = ds.getCoverageStage(i).getProcessor();
220 if (!processor->willUseInputColor()) {
egdaniel3658f382014-09-15 07:01:59 -0700221 firstCoverageStage = i;
222 fInputCoverageIsUsed = false;
223 }
224 }
225#endif
226 if (ds.numCoverageStages() > 0) {
227 fCoverageStages.reset(&ds.getCoverageStage(firstCoverageStage),
228 ds.numCoverageStages() - firstCoverageStage);
229 } else {
230 fCoverageStages.reset();
231 }
232}
233
joshualittb0a8a372014-09-23 09:50:21 -0700234static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
235 if (stage.getFragmentProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700236 *readsDst = true;
237 }
joshualittb0a8a372014-09-23 09:50:21 -0700238 if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700239 *readsFragPosition = true;
240 }
241}
joshualittb0a8a372014-09-23 09:50:21 -0700242
egdaniela7dc0a82014-09-17 08:25:05 -0700243void GrOptDrawState::getStageStats() {
244 // We will need a local coord attrib if there is one currently set on the optState and we are
245 // actually generating some effect code
246 fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
247
248 // if 1 == fVACount then that VA must be position, otherwise it contains some attribute which
249 // will require a vertexShader
250 fRequiresVertexShader = fVACount > 1;
251
252 fReadsDst = false;
253 fReadsFragPosition = false;
254
255 for (int s = 0; s < this->numColorStages(); ++s) {
joshualittb0a8a372014-09-23 09:50:21 -0700256 const GrFragmentStage& stage = this->getColorStage(s);
egdaniela7dc0a82014-09-17 08:25:05 -0700257 get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
258 }
259 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualittb0a8a372014-09-23 09:50:21 -0700260 const GrFragmentStage& stage = this->getCoverageStage(s);
egdaniela7dc0a82014-09-17 08:25:05 -0700261 get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
262 }
263 if (this->hasGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700264 const GrGeometryStage& stage = *this->getGeometryProcessor();
265 fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700266 SkASSERT(fRequiresVertexShader);
267 }
268}
269
egdaniel3658f382014-09-15 07:01:59 -0700270bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
271 return this->isEqual(that);
272}
273