blob: b79e8fce4340df6253c676610b6682a05dea7037 [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.
96 const int* attributeIndices = stage.getVertexAttribIndices();
97 int numAttributes = stage.getVertexAttribIndexCount();
98 for (int i = 0; i < numAttributes; ++i) {
99 int attribIndex = attributeIndices[i];
100 if (attribIndex >= fVACount ||
101 kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
102 return false;
103 }
104
105 GrSLType effectSLType = effect->vertexAttribType(i);
106 GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
107 int slVecCount = GrSLTypeVectorCount(effectSLType);
108 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
109 if (slVecCount != attribVecCount ||
110 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
111 slTypes[attribIndex] != effectSLType)) {
112 return false;
113 }
114 slTypes[attribIndex] = effectSLType;
115 }
116 }
117
118 return true;
119}
120
121bool GrRODrawState::hasSolidCoverage() const {
122 // If we're drawing coverage directly then coverage is effectively treated as color.
123 if (this->isCoverageDrawing()) {
124 return true;
125 }
126
127 GrColor coverage;
128 uint32_t validComponentFlags;
129 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
130 if (this->hasCoverageVertexAttribute()) {
131 validComponentFlags = 0;
132 } else {
133 coverage = fCoverage;
134 validComponentFlags = kRGBA_GrColorComponentFlags;
135 }
136
137 // Run through the coverage stages and see if the coverage will be all ones at the end.
joshualittbd769d02014-09-04 08:56:46 -0700138 if (this->hasGeometryProcessor()) {
139 const GrEffect* effect = fGeometryProcessor->getEffect();
140 effect->getConstantColorComponents(&coverage, &validComponentFlags);
141 }
egdaniel21aed572014-08-26 12:24:06 -0700142 for (int s = 0; s < this->numCoverageStages(); ++s) {
143 const GrEffect* effect = this->getCoverageStage(s).getEffect();
144 effect->getConstantColorComponents(&coverage, &validComponentFlags);
145 }
146 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
147}
148
149////////////////////////////////////////////////////////////////////////////////
150
151bool GrRODrawState::willEffectReadDstColor() const {
152 if (!this->isColorWriteDisabled()) {
153 for (int s = 0; s < this->numColorStages(); ++s) {
154 if (this->getColorStage(s).getEffect()->willReadDstColor()) {
155 return true;
156 }
157 }
158 }
159 for (int s = 0; s < this->numCoverageStages(); ++s) {
160 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) {
161 return true;
162 }
163 }
joshualittbd769d02014-09-04 08:56:46 -0700164 if (this->hasGeometryProcessor()) {
165 if (fGeometryProcessor->getEffect()->willReadDstColor()) {
166 return true;
167 }
168 }
egdaniel21aed572014-08-26 12:24:06 -0700169 return false;
170}
171
172////////////////////////////////////////////////////////////////////////////////
173
egdaniel3658f382014-09-15 07:01:59 -0700174GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
175 GrBlendCoeff* srcCoeff,
176 GrBlendCoeff* dstCoeff) const {
177 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
178 if (NULL == srcCoeff) {
179 srcCoeff = &bogusSrcCoeff;
180 }
181 if (NULL == dstCoeff) {
182 dstCoeff = &bogusDstCoeff;
183 }
184
185 if (forceCoverage) {
186 return this->calcBlendOpts(true, srcCoeff, dstCoeff);
187 }
188
189 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
190 *srcCoeff = fOptSrcBlend;
191 *dstCoeff = fOptDstBlend;
192 return fBlendOptFlags;
193 }
194
195 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
196 fOptSrcBlend = *srcCoeff;
197 fOptDstBlend = *dstCoeff;
198
199 return fBlendOptFlags;
200}
201
202GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage,
203 GrBlendCoeff* srcCoeff,
204 GrBlendCoeff* dstCoeff) const {
205 *srcCoeff = this->getSrcBlendCoeff();
206 *dstCoeff = this->getDstBlendCoeff();
207
208 if (this->isColorWriteDisabled()) {
209 *srcCoeff = kZero_GrBlendCoeff;
210 *dstCoeff = kOne_GrBlendCoeff;
211 }
212
213 bool srcAIsOne = this->srcAlphaWillBeOne();
214 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
215 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
216 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
217 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
218
219 // When coeffs are (0,1) there is no reason to draw at all, unless
220 // stenciling is enabled. Having color writes disabled is effectively
221 // (0,1).
222 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
223 if (this->getStencil().doesWrite()) {
224 return kEmitCoverage_BlendOptFlag;
225 } else {
226 return kSkipDraw_BlendOptFlag;
227 }
228 }
229
230 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
231
232 // if we don't have coverage we can check whether the dst
233 // has to read at all. If not, we'll disable blending.
234 if (!hasCoverage) {
235 if (dstCoeffIsZero) {
236 if (kOne_GrBlendCoeff == *srcCoeff) {
237 // if there is no coverage and coeffs are (1,0) then we
238 // won't need to read the dst at all, it gets replaced by src
239 *dstCoeff = kZero_GrBlendCoeff;
240 return kNone_BlendOpt;
241 } else if (kZero_GrBlendCoeff == *srcCoeff) {
242 // if the op is "clear" then we don't need to emit a color
243 // or blend, just write transparent black into the dst.
244 *srcCoeff = kOne_GrBlendCoeff;
245 *dstCoeff = kZero_GrBlendCoeff;
246 return kEmitTransBlack_BlendOptFlag;
247 }
248 }
249 } else if (this->isCoverageDrawing()) {
250 // we have coverage but we aren't distinguishing it from alpha by request.
251 return kCoverageAsAlpha_BlendOptFlag;
252 } else {
253 // check whether coverage can be safely rolled into alpha
254 // of if we can skip color computation and just emit coverage
255 if (this->canTweakAlphaForCoverage()) {
256 return kCoverageAsAlpha_BlendOptFlag;
257 }
258 if (dstCoeffIsZero) {
259 if (kZero_GrBlendCoeff == *srcCoeff) {
260 // the source color is not included in the blend
261 // the dst coeff is effectively zero so blend works out to:
262 // (c)(0)D + (1-c)D = (1-c)D.
263 *dstCoeff = kISA_GrBlendCoeff;
264 return kEmitCoverage_BlendOptFlag;
265 } else if (srcAIsOne) {
266 // the dst coeff is effectively zero so blend works out to:
267 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
268 // If Sa is 1 then we can replace Sa with c
269 // and set dst coeff to 1-Sa.
270 *dstCoeff = kISA_GrBlendCoeff;
271 return kCoverageAsAlpha_BlendOptFlag;
272 }
273 } else if (dstCoeffIsOne) {
274 // the dst coeff is effectively one so blend works out to:
275 // cS + (c)(1)D + (1-c)D = cS + D.
276 *dstCoeff = kOne_GrBlendCoeff;
277 return kCoverageAsAlpha_BlendOptFlag;
278 }
279 }
280
281 return kNone_BlendOpt;
282}
283
284////////////////////////////////////////////////////////////////////////////////
285
egdaniel21aed572014-08-26 12:24:06 -0700286// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
287// others will blend incorrectly.
288bool GrRODrawState::canTweakAlphaForCoverage() const {
289 /*
290 The fractional coverage is f.
291 The src and dst coeffs are Cs and Cd.
292 The dst and src colors are S and D.
293 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
294 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
295 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
296 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
297 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
298 color by definition.
299 */
300 return kOne_GrBlendCoeff == fDstBlend ||
301 kISA_GrBlendCoeff == fDstBlend ||
302 kISC_GrBlendCoeff == fDstBlend ||
303 this->isCoverageDrawing();
304}
305
bsalomon2a9ca782014-09-05 14:27:43 -0700306void GrRODrawState::convertToPendingExec() {
307 fRenderTarget.markPendingIO();
308 fRenderTarget.removeRef();
309 for (int i = 0; i < fColorStages.count(); ++i) {
310 fColorStages[i].convertToPendingExec();
311 }
312 if (fGeometryProcessor) {
313 fGeometryProcessor->convertToPendingExec();
314 }
315 for (int i = 0; i < fCoverageStages.count(); ++i) {
316 fCoverageStages[i].convertToPendingExec();
317 }
318}
egdaniel3658f382014-09-15 07:01:59 -0700319
320bool GrRODrawState::srcAlphaWillBeOne() const {
321 uint32_t validComponentFlags;
322 GrColor color;
323 // Check if per-vertex or constant color may have partial alpha
324 if (this->hasColorVertexAttribute()) {
325 if (fHints & kVertexColorsAreOpaque_Hint) {
326 validComponentFlags = kA_GrColorComponentFlag;
327 color = 0xFF << GrColor_SHIFT_A;
328 } else {
329 validComponentFlags = 0;
330 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
331 }
332 } else {
333 validComponentFlags = kRGBA_GrColorComponentFlags;
334 color = this->getColor();
335 }
336
337 // Run through the color stages
338 for (int s = 0; s < this->numColorStages(); ++s) {
339 const GrEffect* effect = this->getColorStage(s).getEffect();
340 effect->getConstantColorComponents(&color, &validComponentFlags);
341 }
342
343 // Check whether coverage is treated as color. If so we run through the coverage computation.
344 if (this->isCoverageDrawing()) {
345 // The shader generated for coverage drawing runs the full coverage computation and then
346 // makes the shader output be the multiplication of color and coverage. We mirror that here.
347 GrColor coverage;
348 uint32_t coverageComponentFlags;
349 if (this->hasCoverageVertexAttribute()) {
350 coverageComponentFlags = 0;
351 coverage = 0; // suppresses any warnings.
352 } else {
353 coverageComponentFlags = kRGBA_GrColorComponentFlags;
354 coverage = this->getCoverageColor();
355 }
356
357 // Run through the coverage stages
358 for (int s = 0; s < this->numCoverageStages(); ++s) {
359 const GrEffect* effect = this->getCoverageStage(s).getEffect();
360 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
361 }
362
363 // Since the shader will multiply coverage and color, the only way the final A==1 is if
364 // coverage and color both have A==1.
365 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
366 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
367
368 }
369
370 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
371}
372
373////////////////////////////////////////////////////////////////////////////////
374
375bool GrRODrawState::canIgnoreColorAttribute() const {
376 if (fBlendOptFlags & kInvalid_BlendOptFlag) {
377 this->getBlendOpts();
378 }
379 return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag |
380 GrRODrawState::kEmitCoverage_BlendOptFlag));
381}
382