blob: f7e486f925983522c936d5dc6f96bdf3245dd69f [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
187 if (forceCoverage) {
188 return this->calcBlendOpts(true, srcCoeff, dstCoeff);
189 }
190
191 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
192 *srcCoeff = fOptSrcBlend;
193 *dstCoeff = fOptDstBlend;
194 return fBlendOptFlags;
195 }
196
197 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
198 fOptSrcBlend = *srcCoeff;
199 fOptDstBlend = *dstCoeff;
200
201 return fBlendOptFlags;
202}
203
204GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage,
205 GrBlendCoeff* srcCoeff,
206 GrBlendCoeff* dstCoeff) const {
207 *srcCoeff = this->getSrcBlendCoeff();
208 *dstCoeff = this->getDstBlendCoeff();
209
210 if (this->isColorWriteDisabled()) {
211 *srcCoeff = kZero_GrBlendCoeff;
212 *dstCoeff = kOne_GrBlendCoeff;
213 }
214
215 bool srcAIsOne = this->srcAlphaWillBeOne();
216 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
217 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
218 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
219 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
220
221 // When coeffs are (0,1) there is no reason to draw at all, unless
222 // stenciling is enabled. Having color writes disabled is effectively
223 // (0,1).
224 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
225 if (this->getStencil().doesWrite()) {
226 return kEmitCoverage_BlendOptFlag;
227 } else {
228 return kSkipDraw_BlendOptFlag;
229 }
230 }
231
232 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
233
234 // if we don't have coverage we can check whether the dst
235 // has to read at all. If not, we'll disable blending.
236 if (!hasCoverage) {
237 if (dstCoeffIsZero) {
238 if (kOne_GrBlendCoeff == *srcCoeff) {
239 // if there is no coverage and coeffs are (1,0) then we
240 // won't need to read the dst at all, it gets replaced by src
241 *dstCoeff = kZero_GrBlendCoeff;
242 return kNone_BlendOpt;
243 } else if (kZero_GrBlendCoeff == *srcCoeff) {
244 // if the op is "clear" then we don't need to emit a color
245 // or blend, just write transparent black into the dst.
246 *srcCoeff = kOne_GrBlendCoeff;
247 *dstCoeff = kZero_GrBlendCoeff;
248 return kEmitTransBlack_BlendOptFlag;
249 }
250 }
251 } else if (this->isCoverageDrawing()) {
252 // we have coverage but we aren't distinguishing it from alpha by request.
253 return kCoverageAsAlpha_BlendOptFlag;
254 } else {
255 // check whether coverage can be safely rolled into alpha
256 // of if we can skip color computation and just emit coverage
257 if (this->canTweakAlphaForCoverage()) {
258 return kCoverageAsAlpha_BlendOptFlag;
259 }
260 if (dstCoeffIsZero) {
261 if (kZero_GrBlendCoeff == *srcCoeff) {
262 // the source color is not included in the blend
263 // the dst coeff is effectively zero so blend works out to:
264 // (c)(0)D + (1-c)D = (1-c)D.
265 *dstCoeff = kISA_GrBlendCoeff;
266 return kEmitCoverage_BlendOptFlag;
267 } else if (srcAIsOne) {
268 // the dst coeff is effectively zero so blend works out to:
269 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
270 // If Sa is 1 then we can replace Sa with c
271 // and set dst coeff to 1-Sa.
272 *dstCoeff = kISA_GrBlendCoeff;
273 return kCoverageAsAlpha_BlendOptFlag;
274 }
275 } else if (dstCoeffIsOne) {
276 // the dst coeff is effectively one so blend works out to:
277 // cS + (c)(1)D + (1-c)D = cS + D.
278 *dstCoeff = kOne_GrBlendCoeff;
279 return kCoverageAsAlpha_BlendOptFlag;
280 }
281 }
282
283 return kNone_BlendOpt;
284}
285
286////////////////////////////////////////////////////////////////////////////////
287
egdaniel21aed572014-08-26 12:24:06 -0700288// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
289// others will blend incorrectly.
290bool GrRODrawState::canTweakAlphaForCoverage() const {
291 /*
292 The fractional coverage is f.
293 The src and dst coeffs are Cs and Cd.
294 The dst and src colors are S and D.
295 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
296 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
297 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
298 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
299 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
300 color by definition.
301 */
302 return kOne_GrBlendCoeff == fDstBlend ||
303 kISA_GrBlendCoeff == fDstBlend ||
304 kISC_GrBlendCoeff == fDstBlend ||
305 this->isCoverageDrawing();
306}
307
bsalomon2a9ca782014-09-05 14:27:43 -0700308void GrRODrawState::convertToPendingExec() {
309 fRenderTarget.markPendingIO();
310 fRenderTarget.removeRef();
311 for (int i = 0; i < fColorStages.count(); ++i) {
312 fColorStages[i].convertToPendingExec();
313 }
314 if (fGeometryProcessor) {
315 fGeometryProcessor->convertToPendingExec();
316 }
317 for (int i = 0; i < fCoverageStages.count(); ++i) {
318 fCoverageStages[i].convertToPendingExec();
319 }
320}
egdaniel3658f382014-09-15 07:01:59 -0700321
322bool GrRODrawState::srcAlphaWillBeOne() const {
323 uint32_t validComponentFlags;
324 GrColor color;
325 // Check if per-vertex or constant color may have partial alpha
326 if (this->hasColorVertexAttribute()) {
327 if (fHints & kVertexColorsAreOpaque_Hint) {
328 validComponentFlags = kA_GrColorComponentFlag;
329 color = 0xFF << GrColor_SHIFT_A;
330 } else {
331 validComponentFlags = 0;
332 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
333 }
334 } else {
335 validComponentFlags = kRGBA_GrColorComponentFlags;
336 color = this->getColor();
337 }
338
339 // Run through the color stages
340 for (int s = 0; s < this->numColorStages(); ++s) {
341 const GrEffect* effect = this->getColorStage(s).getEffect();
342 effect->getConstantColorComponents(&color, &validComponentFlags);
343 }
344
345 // Check whether coverage is treated as color. If so we run through the coverage computation.
346 if (this->isCoverageDrawing()) {
347 // The shader generated for coverage drawing runs the full coverage computation and then
348 // makes the shader output be the multiplication of color and coverage. We mirror that here.
349 GrColor coverage;
350 uint32_t coverageComponentFlags;
351 if (this->hasCoverageVertexAttribute()) {
352 coverageComponentFlags = 0;
353 coverage = 0; // suppresses any warnings.
354 } else {
355 coverageComponentFlags = kRGBA_GrColorComponentFlags;
356 coverage = this->getCoverageColor();
357 }
358
359 // Run through the coverage stages
360 for (int s = 0; s < this->numCoverageStages(); ++s) {
361 const GrEffect* effect = this->getCoverageStage(s).getEffect();
362 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
363 }
364
365 // Since the shader will multiply coverage and color, the only way the final A==1 is if
366 // coverage and color both have A==1.
367 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
368 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
369
370 }
371
372 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
373}
374
375////////////////////////////////////////////////////////////////////////////////
376
377bool GrRODrawState::canIgnoreColorAttribute() const {
378 if (fBlendOptFlags & kInvalid_BlendOptFlag) {
379 this->getBlendOpts();
380 }
381 return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag |
382 GrRODrawState::kEmitCoverage_BlendOptFlag));
383}
384