blob: 1b40642251e87219f321d6a3e6aeeb836db6e84c [file] [log] [blame]
bsalomon@google.comaf84e742012-10-05 13:23:24 +00001/*
2 * Copyright 2012 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 "GrDrawState.h"
bsalomon@google.comaf84e742012-10-05 13:23:24 +00009#include "GrPaint.h"
10
bsalomon@google.com137f1342013-05-29 21:27:53 +000011bool GrDrawState::setIdentityViewMatrix() {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000012 if (fColorStages.count() || fCoverageStages.count()) {
13 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -070014 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000015 // sad trombone sound
16 return false;
17 }
18 for (int s = 0; s < fColorStages.count(); ++s) {
19 fColorStages[s].localCoordChange(invVM);
20 }
21 for (int s = 0; s < fCoverageStages.count(); ++s) {
22 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +000023 }
24 }
bsalomon2ed5ef82014-07-07 08:44:05 -070025 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +000026 return true;
27}
28
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000029void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000030 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000031
32 fColorStages.reset();
33 fCoverageStages.reset();
34
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +000035 for (int i = 0; i < paint.numColorStages(); ++i) {
36 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000037 }
38
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +000039 for (int i = 0; i < paint.numCoverageStages(); ++i) {
40 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000041 }
42
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000043 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000044
bsalomon2ed5ef82014-07-07 08:44:05 -070045 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000046
47 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -070048 fBlendConstant = 0x0;
49 fDrawFace = kBoth_DrawFace;
50 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000051 this->resetStateFlags();
52
bsalomon@google.com21c10c52013-06-13 17:44:07 +000053 // Enable the clip bit
54 this->enableState(GrDrawState::kClip_StateBit);
55
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000056 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000057 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
58 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000059
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000060 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000061 this->setCoverage(paint.getCoverage());
egdaniel9514d242014-07-18 06:15:43 -070062 this->invalidateBlendOptFlags();
bsalomon@google.comaf84e742012-10-05 13:23:24 +000063}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000064
65////////////////////////////////////////////////////////////////////////////////
66
jvanverth@google.com9b855c72013-03-01 18:21:22 +000067static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
68 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000069#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000070 uint32_t overlapCheck = 0;
71#endif
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000072 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000073 size_t size = 0;
74 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000075 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000076 size += attribSize;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000077#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078 size_t dwordCount = attribSize >> 2;
79 uint32_t mask = (1 << dwordCount)-1;
80 size_t offsetShift = attribs[index].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000081 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +000082 overlapCheck |= (mask << offsetShift);
83#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000084 }
85 return size;
86}
87
jvanverth@google.com9b855c72013-03-01 18:21:22 +000088size_t GrDrawState::getVertexSize() const {
bsalomon2ed5ef82014-07-07 08:44:05 -070089 return vertex_size(fVAPtr, fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000090}
91
jvanverth@google.comcc782382013-01-28 20:39:48 +000092////////////////////////////////////////////////////////////////////////////////
93
jvanverth@google.com9b855c72013-03-01 18:21:22 +000094void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000095 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +000096
bsalomon2ed5ef82014-07-07 08:44:05 -070097 fVAPtr = attribs;
98 fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +000099
100 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700101 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000102 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700103 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000104#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000105 uint32_t overlapCheck = 0;
106#endif
107 for (int i = 0; i < count; ++i) {
108 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
109 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700110 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000111 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000112 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700113 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000114 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000115#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000116 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
117 uint32_t mask = (1 << dwordCount)-1;
118 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000119 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000120 overlapCheck |= (mask << offsetShift);
121#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000122 }
egdaniel9514d242014-07-18 06:15:43 -0700123 this->invalidateBlendOptFlags();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000124 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700125 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000126}
127
128////////////////////////////////////////////////////////////////////////////////
129
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000130void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000131 static const GrVertexAttrib kPositionAttrib =
132 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000133
bsalomon2ed5ef82014-07-07 08:44:05 -0700134 fVAPtr = &kPositionAttrib;
135 fVACount = 1;
robertphillips@google.com42903302013-04-20 12:26:07 +0000136
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700138 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000139 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700140 sizeof(fFixedFunctionVertexAttribIndices));
141 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel9514d242014-07-18 06:15:43 -0700142 this->invalidateBlendOptFlags();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000143}
144
145////////////////////////////////////////////////////////////////////////////////
146
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000147bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000148 // check consistency of effects and attributes
149 GrSLType slTypes[kMaxVertexAttribCnt];
150 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
151 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000152 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000153 int totalStages = fColorStages.count() + fCoverageStages.count();
154 for (int s = 0; s < totalStages; ++s) {
155 int covIdx = s - fColorStages.count();
156 const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
bsalomonf99f8842014-07-07 11:54:23 -0700157 const GrEffect* effect = stage.getEffect();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000158 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000159 // make sure that any attribute indices have the correct binding type, that the attrib
160 // type and effect's shader lang type are compatible, and that attributes shared by
161 // multiple effects use the same shader lang type.
162 const int* attributeIndices = stage.getVertexAttribIndices();
163 int numAttributes = stage.getVertexAttribIndexCount();
164 for (int i = 0; i < numAttributes; ++i) {
165 int attribIndex = attributeIndices[i];
bsalomon2ed5ef82014-07-07 08:44:05 -0700166 if (attribIndex >= fVACount ||
167 kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000168 return false;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000169 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000170
bsalomonf99f8842014-07-07 11:54:23 -0700171 GrSLType effectSLType = effect->vertexAttribType(i);
bsalomon2ed5ef82014-07-07 08:44:05 -0700172 GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000173 int slVecCount = GrSLTypeVectorCount(effectSLType);
174 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
175 if (slVecCount != attribVecCount ||
176 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
177 slTypes[attribIndex] != effectSLType)) {
178 return false;
179 }
180 slTypes[attribIndex] = effectSLType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000181 }
182 }
183
184 return true;
185}
186
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000187bool GrDrawState::willEffectReadDstColor() const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000188 if (!this->isColorWriteDisabled()) {
189 for (int s = 0; s < fColorStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700190 if (fColorStages[s].getEffect()->willReadDstColor()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000191 return true;
192 }
193 }
194 }
195 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700196 if (fCoverageStages[s].getEffect()->willReadDstColor()) {
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000197 return true;
198 }
199 }
200 return false;
201}
202
jvanverth@google.comcc782382013-01-28 20:39:48 +0000203////////////////////////////////////////////////////////////////////////////////
204
jvanverth@google.com054ae992013-04-01 20:06:51 +0000205bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000206 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000207 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000208 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000209 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000211 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000212 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000213 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000214 color = this->getColor();
215 }
216
217 // Run through the color stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000218 for (int s = 0; s < fColorStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700219 const GrEffect* effect = fColorStages[s].getEffect();
220 effect->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000221 }
222
jvanverth@google.comcc782382013-01-28 20:39:48 +0000223 // Check whether coverage is treated as color. If so we run through the coverage computation.
224 if (this->isCoverageDrawing()) {
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000225 GrColor coverageColor = this->getCoverageColor();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000226 GrColor oldColor = color;
227 color = 0;
228 for (int c = 0; c < 4; ++c) {
229 if (validComponentFlags & (1 << c)) {
230 U8CPU a = (oldColor >> (c * 8)) & 0xff;
231 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
232 color |= (SkMulDiv255Round(a, b) << (c * 8));
233 }
234 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000235 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700236 const GrEffect* effect = fCoverageStages[s].getEffect();
237 effect->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000238 }
239 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000240 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000241}
242
jvanverth@google.com054ae992013-04-01 20:06:51 +0000243bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000244 // If we're drawing coverage directly then coverage is effectively treated as color.
245 if (this->isCoverageDrawing()) {
246 return true;
247 }
248
249 GrColor coverage;
250 uint32_t validComponentFlags;
251 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000252 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000253 validComponentFlags = 0;
254 } else {
bsalomon2ed5ef82014-07-07 08:44:05 -0700255 coverage = fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000256 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000257 }
258
259 // Run through the coverage stages and see if the coverage will be all ones at the end.
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000260 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700261 const GrEffect* effect = fCoverageStages[s].getEffect();
262 effect->getConstantColorComponents(&coverage, &validComponentFlags);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000264 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000265}
266
jvanverth@google.comcc782382013-01-28 20:39:48 +0000267////////////////////////////////////////////////////////////////////////////////
268
bsalomon@google.com2b446732013-02-12 16:47:41 +0000269// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
270// others will blend incorrectly.
271bool GrDrawState::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 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700283 return kOne_GrBlendCoeff == fDstBlend ||
284 kISA_GrBlendCoeff == fDstBlend ||
285 kISC_GrBlendCoeff == fDstBlend ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000286 this->isCoverageDrawing();
287}
288
289GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
290 GrBlendCoeff* srcCoeff,
291 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000292 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
293 if (NULL == srcCoeff) {
294 srcCoeff = &bogusSrcCoeff;
295 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000296 if (NULL == dstCoeff) {
297 dstCoeff = &bogusDstCoeff;
298 }
egdaniel9514d242014-07-18 06:15:43 -0700299
300 if (forceCoverage) {
301 return this->calcBlendOpts(true, srcCoeff, dstCoeff);
302 }
303
304 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
305 *srcCoeff = fOptSrcBlend;
306 *dstCoeff = fOptDstBlend;
307 return fBlendOptFlags;
308 }
309
310 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
311 fOptSrcBlend = *srcCoeff;
312 fOptDstBlend = *dstCoeff;
313
314 return fBlendOptFlags;
315}
316
317GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
318 GrBlendCoeff* srcCoeff,
319 GrBlendCoeff* dstCoeff) const {
320 *srcCoeff = this->getSrcBlendCoeff();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000321 *dstCoeff = this->getDstBlendCoeff();
322
323 if (this->isColorWriteDisabled()) {
324 *srcCoeff = kZero_GrBlendCoeff;
325 *dstCoeff = kOne_GrBlendCoeff;
326 }
327
jvanverth@google.com054ae992013-04-01 20:06:51 +0000328 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000329 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
330 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
331 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
332 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
333
334 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000335 !this->hasCoverageVertexAttribute() &&
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000336 0 == this->getCoverageColor();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000337 // When coeffs are (0,1) there is no reason to draw at all, unless
338 // stenciling is enabled. Having color writes disabled is effectively
339 // (0,1). The same applies when coverage is known to be 0.
340 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
341 if (this->getStencil().doesWrite()) {
egdaniel0f1a7c42014-07-30 13:18:32 -0700342 return kEmitCoverage_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000343 } else {
344 return kSkipDraw_BlendOptFlag;
345 }
346 }
347
bsalomon@google.com4647f902013-03-26 14:45:27 +0000348 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000349 bool hasCoverage = forceCoverage ||
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000350 0xffffffff != this->getCoverageColor() ||
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000351 this->hasCoverageVertexAttribute() ||
352 fCoverageStages.count() > 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000353
354 // if we don't have coverage we can check whether the dst
355 // has to read at all. If not, we'll disable blending.
356 if (!hasCoverage) {
357 if (dstCoeffIsZero) {
358 if (kOne_GrBlendCoeff == *srcCoeff) {
359 // if there is no coverage and coeffs are (1,0) then we
360 // won't need to read the dst at all, it gets replaced by src
egdaniel0f1a7c42014-07-30 13:18:32 -0700361 *dstCoeff = kZero_GrBlendCoeff;
362 return kNone_BlendOpt;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000363 } else if (kZero_GrBlendCoeff == *srcCoeff) {
364 // if the op is "clear" then we don't need to emit a color
365 // or blend, just write transparent black into the dst.
366 *srcCoeff = kOne_GrBlendCoeff;
367 *dstCoeff = kZero_GrBlendCoeff;
egdaniel0f1a7c42014-07-30 13:18:32 -0700368 return kEmitTransBlack_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000369 }
370 }
371 } else if (this->isCoverageDrawing()) {
372 // we have coverage but we aren't distinguishing it from alpha by request.
373 return kCoverageAsAlpha_BlendOptFlag;
374 } else {
375 // check whether coverage can be safely rolled into alpha
376 // of if we can skip color computation and just emit coverage
377 if (this->canTweakAlphaForCoverage()) {
378 return kCoverageAsAlpha_BlendOptFlag;
379 }
380 if (dstCoeffIsZero) {
381 if (kZero_GrBlendCoeff == *srcCoeff) {
382 // the source color is not included in the blend
383 // the dst coeff is effectively zero so blend works out to:
384 // (c)(0)D + (1-c)D = (1-c)D.
385 *dstCoeff = kISA_GrBlendCoeff;
386 return kEmitCoverage_BlendOptFlag;
387 } else if (srcAIsOne) {
388 // the dst coeff is effectively zero so blend works out to:
389 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
390 // If Sa is 1 then we can replace Sa with c
391 // and set dst coeff to 1-Sa.
392 *dstCoeff = kISA_GrBlendCoeff;
393 return kCoverageAsAlpha_BlendOptFlag;
394 }
395 } else if (dstCoeffIsOne) {
396 // the dst coeff is effectively one so blend works out to:
397 // cS + (c)(1)D + (1-c)D = cS + D.
398 *dstCoeff = kOne_GrBlendCoeff;
399 return kCoverageAsAlpha_BlendOptFlag;
400 }
401 }
egdaniel0f1a7c42014-07-30 13:18:32 -0700402
bsalomon@google.com2b446732013-02-12 16:47:41 +0000403 return kNone_BlendOpt;
404}
405
egdaniel02cafcc2014-07-21 11:37:28 -0700406bool GrDrawState::canIgnoreColorAttribute() const {
407 if (fBlendOptFlags & kInvalid_BlendOptFlag) {
408 this->getBlendOpts();
409 }
410 return SkToBool(fBlendOptFlags & (GrDrawState::kEmitTransBlack_BlendOptFlag |
411 GrDrawState::kEmitCoverage_BlendOptFlag));
412}
413
414
bsalomon@google.com2b446732013-02-12 16:47:41 +0000415////////////////////////////////////////////////////////////////////////////////
416
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000417void GrDrawState::AutoViewMatrixRestore::restore() {
418 if (NULL != fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000419 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700420 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000421 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000422 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000423 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000424
425 int i = 0;
426 for (int s = 0; s < fNumColorStages; ++s, ++i) {
427 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
428 }
429 for (int s = 0; s < numCoverageStages; ++s, ++i) {
430 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000431 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000432 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000433 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000434}
435
436void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000437 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000438 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000439
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000440 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000441 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000442 return;
443 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000444 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000445
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000446 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700447 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000448
449 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000450 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000451}
452
bsalomon@google.com137f1342013-05-29 21:27:53 +0000453bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000454 this->restore();
455
bsalomon@google.com137f1342013-05-29 21:27:53 +0000456 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000457 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000458 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000459
bsalomon@google.com137f1342013-05-29 21:27:53 +0000460 if (drawState->getViewMatrix().isIdentity()) {
461 return true;
462 }
463
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000464 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000465 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700466 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000467 fDrawState = drawState;
468 fNumColorStages = 0;
469 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000470 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000471 return true;
472 } else {
473 SkMatrix inv;
474 if (!fViewMatrix.invert(&inv)) {
475 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000476 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700477 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000478 fDrawState = drawState;
479 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000480 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000481 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000482 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000483}
484
485void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
486 fSavedCoordChanges.reset(fDrawState->numTotalStages());
487 int i = 0;
488
489 fNumColorStages = fDrawState->numColorStages();
490 for (int s = 0; s < fNumColorStages; ++s, ++i) {
491 fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
492 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000493 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000494
495 int numCoverageStages = fDrawState->numCoverageStages();
496 for (int s = 0; s < numCoverageStages; ++s, ++i) {
497 fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
498 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
499 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000500}