blob: e522008cae4ab7c256b602d75330dde1bc0b6ac5 [file] [log] [blame]
egdaniel21aed572014-08-26 12:24:06 -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 "GrRODrawState.h"
egdaniel3658f382014-09-15 07:01:59 -07009
egdaniel21aed572014-08-26 12:24:06 -070010#include "GrDrawTargetCaps.h"
egdaniel3658f382014-09-15 07:01:59 -070011#include "GrRenderTarget.h"
egdaniel21aed572014-08-26 12:24:06 -070012
13////////////////////////////////////////////////////////////////////////////////
14
egdaniel3658f382014-09-15 07:01:59 -070015GrRODrawState::GrRODrawState(const GrRODrawState& drawState) : INHERITED() {
16 fRenderTarget.setResource(SkSafeRef(drawState.fRenderTarget.getResource()),
17 GrProgramResource::kWrite_IOType);
18}
19
egdaniel21aed572014-08-26 12:24:06 -070020bool GrRODrawState::isEqual(const GrRODrawState& that) const {
21 bool usingVertexColors = this->hasColorVertexAttribute();
22 if (!usingVertexColors && this->fColor != that.fColor) {
23 return false;
24 }
25
bsalomon2a9ca782014-09-05 14:27:43 -070026 if (this->getRenderTarget() != that.getRenderTarget() ||
egdaniel21aed572014-08-26 12:24:06 -070027 this->fColorStages.count() != that.fColorStages.count() ||
28 this->fCoverageStages.count() != that.fCoverageStages.count() ||
29 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
30 this->fSrcBlend != that.fSrcBlend ||
31 this->fDstBlend != that.fDstBlend ||
32 this->fBlendConstant != that.fBlendConstant ||
33 this->fFlagBits != that.fFlagBits ||
34 this->fVACount != that.fVACount ||
egdaniel7b3d5ee2014-08-28 05:41:14 -070035 this->fVAStride != that.fVAStride ||
egdaniel21aed572014-08-26 12:24:06 -070036 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
37 this->fStencilSettings != that.fStencilSettings ||
38 this->fDrawFace != that.fDrawFace) {
39 return false;
40 }
41
42 bool usingVertexCoverage = this->hasCoverageVertexAttribute();
43 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
44 return false;
45 }
46
47 bool explicitLocalCoords = this->hasLocalCoordAttribute();
joshualittbd769d02014-09-04 08:56:46 -070048 if (this->hasGeometryProcessor()) {
49 if (!that.hasGeometryProcessor()) {
joshualitt5a80be22014-09-05 10:45:30 -070050 return false;
joshualittbd769d02014-09-04 08:56:46 -070051 } else if (!GrEffectStage::AreCompatible(*this->getGeometryProcessor(),
52 *that.getGeometryProcessor(),
53 explicitLocalCoords)) {
joshualitt5a80be22014-09-05 10:45:30 -070054 return false;
joshualittbd769d02014-09-04 08:56:46 -070055 }
56 } else if (that.hasGeometryProcessor()) {
joshualitt5a80be22014-09-05 10:45:30 -070057 return false;
joshualittbd769d02014-09-04 08:56:46 -070058 }
59
egdaniel21aed572014-08-26 12:24:06 -070060 for (int i = 0; i < this->numColorStages(); i++) {
61 if (!GrEffectStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
62 explicitLocalCoords)) {
63 return false;
64 }
65 }
66 for (int i = 0; i < this->numCoverageStages(); i++) {
67 if (!GrEffectStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
68 explicitLocalCoords)) {
69 return false;
70 }
71 }
72
egdaniel21aed572014-08-26 12:24:06 -070073 SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
74 that.fFixedFunctionVertexAttribIndices,
75 sizeof(this->fFixedFunctionVertexAttribIndices)));
76
77 return true;
78}
79
80////////////////////////////////////////////////////////////////////////////////
81
82bool GrRODrawState::validateVertexAttribs() const {
83 // check consistency of effects and attributes
84 GrSLType slTypes[kMaxVertexAttribCnt];
85 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
86 slTypes[i] = static_cast<GrSLType>(-1);
87 }
joshualittbd769d02014-09-04 08:56:46 -070088
89 if (this->hasGeometryProcessor()) {
90 const GrEffectStage& stage = *this->getGeometryProcessor();
egdaniel21aed572014-08-26 12:24:06 -070091 const GrEffect* effect = stage.getEffect();
bsalomon49f085d2014-09-05 13:34:00 -070092 SkASSERT(effect);
egdaniel21aed572014-08-26 12:24:06 -070093 // make sure that any attribute indices have the correct binding type, that the attrib
94 // type and effect's shader lang type are compatible, and that attributes shared by
95 // multiple effects use the same shader lang type.
joshualitt249af152014-09-15 11:41:13 -070096 const GrEffect::VertexAttribArray& s = effect->getVertexAttribs();
egdaniel21aed572014-08-26 12:24:06 -070097
joshualitt249af152014-09-15 11:41:13 -070098 int effectIndex = 0;
99 for (int index = 0; index < fVACount; index++) {
100 if (kEffect_GrVertexAttribBinding != fVAPtr[index].fBinding) {
101 // we only care about effect bindings
102 continue;
103 }
104 SkASSERT(effectIndex < s.count());
105 GrSLType effectSLType = s[effectIndex].getType();
106 GrVertexAttribType attribType = fVAPtr[index].fType;
egdaniel21aed572014-08-26 12:24:06 -0700107 int slVecCount = GrSLTypeVectorCount(effectSLType);
108 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
109 if (slVecCount != attribVecCount ||
joshualitt249af152014-09-15 11:41:13 -0700110 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
egdaniel21aed572014-08-26 12:24:06 -0700111 return false;
112 }
joshualitt249af152014-09-15 11:41:13 -0700113 slTypes[index] = effectSLType;
114 effectIndex++;
egdaniel21aed572014-08-26 12:24:06 -0700115 }
joshualitt249af152014-09-15 11:41:13 -0700116 // Make sure all attributes are consumed and we were able to find everything
117 SkASSERT(s.count() == effectIndex);
egdaniel21aed572014-08-26 12:24:06 -0700118 }
119
120 return true;
121}
122
123bool GrRODrawState::hasSolidCoverage() const {
124 // If we're drawing coverage directly then coverage is effectively treated as color.
125 if (this->isCoverageDrawing()) {
126 return true;
127 }
128
129 GrColor coverage;
130 uint32_t validComponentFlags;
131 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
132 if (this->hasCoverageVertexAttribute()) {
133 validComponentFlags = 0;
134 } else {
135 coverage = fCoverage;
136 validComponentFlags = kRGBA_GrColorComponentFlags;
137 }
138
139 // Run through the coverage stages and see if the coverage will be all ones at the end.
joshualittbd769d02014-09-04 08:56:46 -0700140 if (this->hasGeometryProcessor()) {
141 const GrEffect* effect = fGeometryProcessor->getEffect();
142 effect->getConstantColorComponents(&coverage, &validComponentFlags);
143 }
egdaniel21aed572014-08-26 12:24:06 -0700144 for (int s = 0; s < this->numCoverageStages(); ++s) {
145 const GrEffect* effect = this->getCoverageStage(s).getEffect();
146 effect->getConstantColorComponents(&coverage, &validComponentFlags);
147 }
148 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
149}
150
151////////////////////////////////////////////////////////////////////////////////
152
153bool GrRODrawState::willEffectReadDstColor() const {
154 if (!this->isColorWriteDisabled()) {
155 for (int s = 0; s < this->numColorStages(); ++s) {
156 if (this->getColorStage(s).getEffect()->willReadDstColor()) {
157 return true;
158 }
159 }
160 }
161 for (int s = 0; s < this->numCoverageStages(); ++s) {
162 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) {
163 return true;
164 }
165 }
joshualittbd769d02014-09-04 08:56:46 -0700166 if (this->hasGeometryProcessor()) {
167 if (fGeometryProcessor->getEffect()->willReadDstColor()) {
168 return true;
169 }
170 }
egdaniel21aed572014-08-26 12:24:06 -0700171 return false;
172}
173
174////////////////////////////////////////////////////////////////////////////////
175
egdaniel3658f382014-09-15 07:01:59 -0700176GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
177 GrBlendCoeff* srcCoeff,
178 GrBlendCoeff* dstCoeff) const {
179 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
180 if (NULL == srcCoeff) {
181 srcCoeff = &bogusSrcCoeff;
182 }
183 if (NULL == dstCoeff) {
184 dstCoeff = &bogusDstCoeff;
185 }
186
egdaniel3658f382014-09-15 07:01:59 -0700187 *srcCoeff = this->getSrcBlendCoeff();
188 *dstCoeff = this->getDstBlendCoeff();
189
190 if (this->isColorWriteDisabled()) {
191 *srcCoeff = kZero_GrBlendCoeff;
192 *dstCoeff = kOne_GrBlendCoeff;
193 }
194
195 bool srcAIsOne = this->srcAlphaWillBeOne();
196 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
197 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
198 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
199 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
200
201 // When coeffs are (0,1) there is no reason to draw at all, unless
202 // stenciling is enabled. Having color writes disabled is effectively
203 // (0,1).
204 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
205 if (this->getStencil().doesWrite()) {
206 return kEmitCoverage_BlendOptFlag;
207 } else {
208 return kSkipDraw_BlendOptFlag;
209 }
210 }
211
212 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
213
214 // if we don't have coverage we can check whether the dst
215 // has to read at all. If not, we'll disable blending.
216 if (!hasCoverage) {
217 if (dstCoeffIsZero) {
218 if (kOne_GrBlendCoeff == *srcCoeff) {
219 // if there is no coverage and coeffs are (1,0) then we
220 // won't need to read the dst at all, it gets replaced by src
221 *dstCoeff = kZero_GrBlendCoeff;
222 return kNone_BlendOpt;
223 } else if (kZero_GrBlendCoeff == *srcCoeff) {
224 // if the op is "clear" then we don't need to emit a color
225 // or blend, just write transparent black into the dst.
226 *srcCoeff = kOne_GrBlendCoeff;
227 *dstCoeff = kZero_GrBlendCoeff;
228 return kEmitTransBlack_BlendOptFlag;
229 }
230 }
231 } else if (this->isCoverageDrawing()) {
232 // we have coverage but we aren't distinguishing it from alpha by request.
233 return kCoverageAsAlpha_BlendOptFlag;
234 } else {
235 // check whether coverage can be safely rolled into alpha
236 // of if we can skip color computation and just emit coverage
237 if (this->canTweakAlphaForCoverage()) {
238 return kCoverageAsAlpha_BlendOptFlag;
239 }
240 if (dstCoeffIsZero) {
241 if (kZero_GrBlendCoeff == *srcCoeff) {
242 // the source color is not included in the blend
243 // the dst coeff is effectively zero so blend works out to:
244 // (c)(0)D + (1-c)D = (1-c)D.
245 *dstCoeff = kISA_GrBlendCoeff;
246 return kEmitCoverage_BlendOptFlag;
247 } else if (srcAIsOne) {
248 // the dst coeff is effectively zero so blend works out to:
249 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
250 // If Sa is 1 then we can replace Sa with c
251 // and set dst coeff to 1-Sa.
252 *dstCoeff = kISA_GrBlendCoeff;
253 return kCoverageAsAlpha_BlendOptFlag;
254 }
255 } else if (dstCoeffIsOne) {
256 // the dst coeff is effectively one so blend works out to:
257 // cS + (c)(1)D + (1-c)D = cS + D.
258 *dstCoeff = kOne_GrBlendCoeff;
259 return kCoverageAsAlpha_BlendOptFlag;
260 }
261 }
262
263 return kNone_BlendOpt;
264}
265
266////////////////////////////////////////////////////////////////////////////////
267
egdaniel21aed572014-08-26 12:24:06 -0700268// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
269// others will blend incorrectly.
270bool GrRODrawState::canTweakAlphaForCoverage() const {
271 /*
272 The fractional coverage is f.
273 The src and dst coeffs are Cs and Cd.
274 The dst and src colors are S and D.
275 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
276 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
277 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
278 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
279 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
280 color by definition.
281 */
282 return kOne_GrBlendCoeff == fDstBlend ||
283 kISA_GrBlendCoeff == fDstBlend ||
284 kISC_GrBlendCoeff == fDstBlend ||
285 this->isCoverageDrawing();
286}
287
bsalomon2a9ca782014-09-05 14:27:43 -0700288void GrRODrawState::convertToPendingExec() {
289 fRenderTarget.markPendingIO();
290 fRenderTarget.removeRef();
291 for (int i = 0; i < fColorStages.count(); ++i) {
292 fColorStages[i].convertToPendingExec();
293 }
294 if (fGeometryProcessor) {
295 fGeometryProcessor->convertToPendingExec();
296 }
297 for (int i = 0; i < fCoverageStages.count(); ++i) {
298 fCoverageStages[i].convertToPendingExec();
299 }
300}
egdaniel3658f382014-09-15 07:01:59 -0700301
302bool GrRODrawState::srcAlphaWillBeOne() const {
303 uint32_t validComponentFlags;
304 GrColor color;
305 // Check if per-vertex or constant color may have partial alpha
306 if (this->hasColorVertexAttribute()) {
307 if (fHints & kVertexColorsAreOpaque_Hint) {
308 validComponentFlags = kA_GrColorComponentFlag;
309 color = 0xFF << GrColor_SHIFT_A;
310 } else {
311 validComponentFlags = 0;
312 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
313 }
314 } else {
315 validComponentFlags = kRGBA_GrColorComponentFlags;
316 color = this->getColor();
317 }
318
319 // Run through the color stages
320 for (int s = 0; s < this->numColorStages(); ++s) {
321 const GrEffect* effect = this->getColorStage(s).getEffect();
322 effect->getConstantColorComponents(&color, &validComponentFlags);
323 }
324
325 // Check whether coverage is treated as color. If so we run through the coverage computation.
326 if (this->isCoverageDrawing()) {
327 // The shader generated for coverage drawing runs the full coverage computation and then
328 // makes the shader output be the multiplication of color and coverage. We mirror that here.
329 GrColor coverage;
330 uint32_t coverageComponentFlags;
331 if (this->hasCoverageVertexAttribute()) {
332 coverageComponentFlags = 0;
333 coverage = 0; // suppresses any warnings.
334 } else {
335 coverageComponentFlags = kRGBA_GrColorComponentFlags;
336 coverage = this->getCoverageColor();
337 }
338
339 // Run through the coverage stages
340 for (int s = 0; s < this->numCoverageStages(); ++s) {
341 const GrEffect* effect = this->getCoverageStage(s).getEffect();
342 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
343 }
344
345 // Since the shader will multiply coverage and color, the only way the final A==1 is if
346 // coverage and color both have A==1.
347 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
348 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
349
350 }
351
352 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
353}
354