blob: cb03d2d683005dfe063bbedf49cf0cd53b8e933a [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"
11
egdaniel170f90b2014-09-16 12:54:40 -070012GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
13 BlendOptFlags blendOptFlags,
14 GrBlendCoeff optSrcCoeff,
15 GrBlendCoeff optDstCoeff) : INHERITED(drawState) {
egdaniel3658f382014-09-15 07:01:59 -070016 fColor = drawState.getColor();
17 fCoverage = drawState.getCoverage();
18 fViewMatrix = drawState.getViewMatrix();
19 fBlendConstant = drawState.getBlendConstant();
20 fFlagBits = drawState.getFlagBits();
21 fVAPtr = drawState.getVertexAttribs();
22 fVACount = drawState.getVertexAttribCount();
23 fVAStride = drawState.getVertexStride();
24 fStencilSettings = drawState.getStencil();
25 fDrawFace = drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070026 fBlendOptFlags = blendOptFlags;
27 fSrcBlend = optSrcCoeff;
28 fDstBlend = optDstCoeff;
egdaniel3658f382014-09-15 07:01:59 -070029
30 memcpy(fFixedFunctionVertexAttribIndices,
31 drawState.getFixedFunctionVertexAttribIndices(),
32 sizeof(fFixedFunctionVertexAttribIndices));
33
egdaniel170f90b2014-09-16 12:54:40 -070034
egdaniel3658f382014-09-15 07:01:59 -070035 fInputColorIsUsed = true;
36 fInputCoverageIsUsed = true;
37
38 if (drawState.hasGeometryProcessor()) {
39 fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*drawState.getGeometryProcessor())));
40 } else {
41 fGeometryProcessor.reset(NULL);
42 }
43
44 this->copyEffectiveColorStages(drawState);
45 this->copyEffectiveCoverageStages(drawState);
egdaniel170f90b2014-09-16 12:54:40 -070046 this->adjustFromBlendOpts();
egdaniela7dc0a82014-09-17 08:25:05 -070047 this->getStageStats();
egdaniel3658f382014-09-15 07:01:59 -070048};
49
egdaniel170f90b2014-09-16 12:54:40 -070050void GrOptDrawState::adjustFromBlendOpts() {
51
52 switch (fBlendOptFlags) {
53 case kNone_BlendOpt:
54 case kSkipDraw_BlendOptFlag:
55 break;
56 case kCoverageAsAlpha_BlendOptFlag:
57 fFlagBits |= kCoverageDrawing_StateBit;
58 break;
59 case kEmitCoverage_BlendOptFlag:
60 fColor = 0xffffffff;
61 fInputColorIsUsed = true;
62 fColorStages.reset();
63 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
64 break;
65 case kEmitTransBlack_BlendOptFlag:
66 fColor = 0;
67 fCoverage = 0xff;
68 fInputColorIsUsed = true;
69 fInputCoverageIsUsed = true;
70 fColorStages.reset();
71 fCoverageStages.reset();
72 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
73 0x1 << kCoverage_GrVertexAttribBinding);
74 break;
75 default:
76 SkFAIL("Unknown BlendOptFlag");
77
78 }
79}
80
egdaniel3658f382014-09-15 07:01:59 -070081void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
82 int numToRemove = 0;
83 uint8_t maskCheck = 0x1;
84 // Count the number of vertex attributes that we will actually remove
85 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
86 if ((maskCheck & removeVAFlag) && -1 != fFixedFunctionVertexAttribIndices[i]) {
87 ++numToRemove;
88 }
89 maskCheck <<= 1;
90 }
egdaniel170f90b2014-09-16 12:54:40 -070091
egdaniel3658f382014-09-15 07:01:59 -070092 fOptVA.reset(fVACount - numToRemove);
93
94 GrVertexAttrib* dst = fOptVA.get();
95 const GrVertexAttrib* src = fVAPtr;
96
97 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
98 const GrVertexAttrib& currAttrib = *src;
99 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
100 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
101 if (maskCheck & removeVAFlag) {
102 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
103 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
104 continue;
105 }
egdaniel170f90b2014-09-16 12:54:40 -0700106 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700107 }
108 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700109 ++newIdx;
110 ++dst;
111 }
112 fVACount -= numToRemove;
113 fVAPtr = fOptVA.get();
114}
115
116void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
117 int firstColorStage = 0;
118
119 // Set up color and flags for ConstantColorComponent checks
120 GrColor color;
121 uint32_t validComponentFlags;
122 if (!this->hasColorVertexAttribute()) {
123 color = ds.getColor();
124 validComponentFlags = kRGBA_GrColorComponentFlags;
125 } else {
126 if (ds.vertexColorsAreOpaque()) {
127 color = 0xFF << GrColor_SHIFT_A;
128 validComponentFlags = kA_GrColorComponentFlag;
129 } else {
130 validComponentFlags = 0;
131 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
132 }
133 }
134
135 for (int i = 0; i < ds.numColorStages(); ++i) {
136 const GrEffect* effect = ds.getColorStage(i).getEffect();
137 if (!effect->willUseInputColor()) {
138 firstColorStage = i;
139 fInputColorIsUsed = false;
140 }
141 effect->getConstantColorComponents(&color, &validComponentFlags);
142 if (kRGBA_GrColorComponentFlags == validComponentFlags) {
143 firstColorStage = i + 1;
144 fColor = color;
145 fInputColorIsUsed = true;
146 this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
147 }
148 }
149 if (firstColorStage < ds.numColorStages()) {
150 fColorStages.reset(&ds.getColorStage(firstColorStage),
151 ds.numColorStages() - firstColorStage);
152 } else {
153 fColorStages.reset();
154 }
155}
156
157void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
158 int firstCoverageStage = 0;
159
160 // We do not try to optimize out constantColor coverage effects here. It is extremely rare
161 // to have a coverage effect that returns a constant value for all four channels. Thus we
162 // save having to make extra virtual calls by not checking for it.
163
164 // Don't do any optimizations on coverage stages. It should not be the case where we do not use
165 // input coverage in an effect
166#ifdef OptCoverageStages
167 for (int i = 0; i < ds.numCoverageStages(); ++i) {
168 const GrEffect* effect = ds.getCoverageStage(i).getEffect();
169 if (!effect->willUseInputColor()) {
170 firstCoverageStage = i;
171 fInputCoverageIsUsed = false;
172 }
173 }
174#endif
175 if (ds.numCoverageStages() > 0) {
176 fCoverageStages.reset(&ds.getCoverageStage(firstCoverageStage),
177 ds.numCoverageStages() - firstCoverageStage);
178 } else {
179 fCoverageStages.reset();
180 }
181}
182
egdaniela7dc0a82014-09-17 08:25:05 -0700183static void get_stage_stats(const GrEffectStage& stage, bool* readsDst, bool* readsFragPosition) {
184 if (stage.getEffect()->willReadDstColor()) {
185 *readsDst = true;
186 }
187 if (stage.getEffect()->willReadFragmentPosition()) {
188 *readsFragPosition = true;
189 }
190}
191void GrOptDrawState::getStageStats() {
192 // We will need a local coord attrib if there is one currently set on the optState and we are
193 // actually generating some effect code
194 fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
195
196 // if 1 == fVACount then that VA must be position, otherwise it contains some attribute which
197 // will require a vertexShader
198 fRequiresVertexShader = fVACount > 1;
199
200 fReadsDst = false;
201 fReadsFragPosition = false;
202
203 for (int s = 0; s < this->numColorStages(); ++s) {
204 const GrEffectStage& stage = this->getColorStage(s);
205 get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
206 }
207 for (int s = 0; s < this->numCoverageStages(); ++s) {
208 const GrEffectStage& stage = this->getCoverageStage(s);
209 get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
210 }
211 if (this->hasGeometryProcessor()) {
212 const GrEffectStage& stage = *this->getGeometryProcessor();
213 get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
214 SkASSERT(fRequiresVertexShader);
215 }
216}
217
egdaniel3658f382014-09-15 07:01:59 -0700218bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
219 return this->isEqual(that);
220}
221