blob: 4d35684e5c80290216645d47280bda12b71c07e4 [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()),
bsalomonf96ba022014-09-17 08:05:40 -070017 GrGpuResourceRef::kWrite_IOType);
egdaniel3658f382014-09-15 07:01:59 -070018}
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 {
egdaniel170f90b2014-09-16 12:54:40 -0700208 *dstCoeff = kOne_GrBlendCoeff;
egdaniel3658f382014-09-15 07:01:59 -0700209 return kSkipDraw_BlendOptFlag;
210 }
211 }
212
213 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
214
215 // if we don't have coverage we can check whether the dst
216 // has to read at all. If not, we'll disable blending.
217 if (!hasCoverage) {
218 if (dstCoeffIsZero) {
219 if (kOne_GrBlendCoeff == *srcCoeff) {
220 // if there is no coverage and coeffs are (1,0) then we
221 // won't need to read the dst at all, it gets replaced by src
222 *dstCoeff = kZero_GrBlendCoeff;
223 return kNone_BlendOpt;
224 } else if (kZero_GrBlendCoeff == *srcCoeff) {
225 // if the op is "clear" then we don't need to emit a color
226 // or blend, just write transparent black into the dst.
227 *srcCoeff = kOne_GrBlendCoeff;
228 *dstCoeff = kZero_GrBlendCoeff;
229 return kEmitTransBlack_BlendOptFlag;
230 }
231 }
232 } else if (this->isCoverageDrawing()) {
233 // we have coverage but we aren't distinguishing it from alpha by request.
234 return kCoverageAsAlpha_BlendOptFlag;
235 } else {
236 // check whether coverage can be safely rolled into alpha
237 // of if we can skip color computation and just emit coverage
238 if (this->canTweakAlphaForCoverage()) {
239 return kCoverageAsAlpha_BlendOptFlag;
240 }
241 if (dstCoeffIsZero) {
242 if (kZero_GrBlendCoeff == *srcCoeff) {
243 // the source color is not included in the blend
244 // the dst coeff is effectively zero so blend works out to:
245 // (c)(0)D + (1-c)D = (1-c)D.
246 *dstCoeff = kISA_GrBlendCoeff;
247 return kEmitCoverage_BlendOptFlag;
248 } else if (srcAIsOne) {
249 // the dst coeff is effectively zero so blend works out to:
250 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
251 // If Sa is 1 then we can replace Sa with c
252 // and set dst coeff to 1-Sa.
253 *dstCoeff = kISA_GrBlendCoeff;
254 return kCoverageAsAlpha_BlendOptFlag;
255 }
256 } else if (dstCoeffIsOne) {
257 // the dst coeff is effectively one so blend works out to:
258 // cS + (c)(1)D + (1-c)D = cS + D.
259 *dstCoeff = kOne_GrBlendCoeff;
260 return kCoverageAsAlpha_BlendOptFlag;
261 }
262 }
263
264 return kNone_BlendOpt;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268
egdaniel21aed572014-08-26 12:24:06 -0700269// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
270// others will blend incorrectly.
271bool GrRODrawState::canTweakAlphaForCoverage() const {
272 /*
273 The fractional coverage is f.
274 The src and dst coeffs are Cs and Cd.
275 The dst and src colors are S and D.
276 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
277 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
278 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
279 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
280 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
281 color by definition.
282 */
283 return kOne_GrBlendCoeff == fDstBlend ||
284 kISA_GrBlendCoeff == fDstBlend ||
285 kISC_GrBlendCoeff == fDstBlend ||
286 this->isCoverageDrawing();
287}
288
bsalomon2a9ca782014-09-05 14:27:43 -0700289void GrRODrawState::convertToPendingExec() {
290 fRenderTarget.markPendingIO();
291 fRenderTarget.removeRef();
292 for (int i = 0; i < fColorStages.count(); ++i) {
293 fColorStages[i].convertToPendingExec();
294 }
295 if (fGeometryProcessor) {
296 fGeometryProcessor->convertToPendingExec();
297 }
298 for (int i = 0; i < fCoverageStages.count(); ++i) {
299 fCoverageStages[i].convertToPendingExec();
300 }
301}
egdaniel3658f382014-09-15 07:01:59 -0700302
303bool GrRODrawState::srcAlphaWillBeOne() const {
304 uint32_t validComponentFlags;
305 GrColor color;
306 // Check if per-vertex or constant color may have partial alpha
307 if (this->hasColorVertexAttribute()) {
308 if (fHints & kVertexColorsAreOpaque_Hint) {
309 validComponentFlags = kA_GrColorComponentFlag;
310 color = 0xFF << GrColor_SHIFT_A;
311 } else {
312 validComponentFlags = 0;
313 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
314 }
315 } else {
316 validComponentFlags = kRGBA_GrColorComponentFlags;
317 color = this->getColor();
318 }
319
320 // Run through the color stages
321 for (int s = 0; s < this->numColorStages(); ++s) {
322 const GrEffect* effect = this->getColorStage(s).getEffect();
323 effect->getConstantColorComponents(&color, &validComponentFlags);
324 }
325
326 // Check whether coverage is treated as color. If so we run through the coverage computation.
327 if (this->isCoverageDrawing()) {
328 // The shader generated for coverage drawing runs the full coverage computation and then
329 // makes the shader output be the multiplication of color and coverage. We mirror that here.
330 GrColor coverage;
331 uint32_t coverageComponentFlags;
332 if (this->hasCoverageVertexAttribute()) {
333 coverageComponentFlags = 0;
334 coverage = 0; // suppresses any warnings.
335 } else {
336 coverageComponentFlags = kRGBA_GrColorComponentFlags;
337 coverage = this->getCoverageColor();
338 }
339
340 // Run through the coverage stages
341 for (int s = 0; s < this->numCoverageStages(); ++s) {
342 const GrEffect* effect = this->getCoverageStage(s).getEffect();
343 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
344 }
345
346 // Since the shader will multiply coverage and color, the only way the final A==1 is if
347 // coverage and color both have A==1.
348 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
349 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
350
351 }
352
353 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
354}
355