blob: 8285a324d5902ce11d3dc71324ca9b69c3a0bf13 [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());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000062}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000063
64////////////////////////////////////////////////////////////////////////////////
65
jvanverth@google.com9b855c72013-03-01 18:21:22 +000066static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
67 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000068#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000069 uint32_t overlapCheck = 0;
70#endif
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000071 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000072 size_t size = 0;
73 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000074 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000075 size += attribSize;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000076#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000077 size_t dwordCount = attribSize >> 2;
78 uint32_t mask = (1 << dwordCount)-1;
79 size_t offsetShift = attribs[index].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000080 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +000081 overlapCheck |= (mask << offsetShift);
82#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000083 }
84 return size;
85}
86
jvanverth@google.com9b855c72013-03-01 18:21:22 +000087size_t GrDrawState::getVertexSize() const {
bsalomon2ed5ef82014-07-07 08:44:05 -070088 return vertex_size(fVAPtr, fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000089}
90
jvanverth@google.comcc782382013-01-28 20:39:48 +000091////////////////////////////////////////////////////////////////////////////////
92
jvanverth@google.com9b855c72013-03-01 18:21:22 +000093void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000094 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +000095
bsalomon2ed5ef82014-07-07 08:44:05 -070096 fVAPtr = attribs;
97 fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +000098
99 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700100 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000101 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700102 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000103#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000104 uint32_t overlapCheck = 0;
105#endif
106 for (int i = 0; i < count; ++i) {
107 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
108 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700109 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000110 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000111 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700112 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000113 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000114#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000115 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
116 uint32_t mask = (1 << dwordCount)-1;
117 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000118 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000119 overlapCheck |= (mask << offsetShift);
120#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000121 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000122 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700123 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000124}
125
126////////////////////////////////////////////////////////////////////////////////
127
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000128void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000129 static const GrVertexAttrib kPositionAttrib =
130 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000131
bsalomon2ed5ef82014-07-07 08:44:05 -0700132 fVAPtr = &kPositionAttrib;
133 fVACount = 1;
robertphillips@google.com42903302013-04-20 12:26:07 +0000134
jvanverth@google.com054ae992013-04-01 20:06:51 +0000135 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700136 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700138 sizeof(fFixedFunctionVertexAttribIndices));
139 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000140}
141
142////////////////////////////////////////////////////////////////////////////////
143
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000144bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000145 // check consistency of effects and attributes
146 GrSLType slTypes[kMaxVertexAttribCnt];
147 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
148 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000149 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000150 int totalStages = fColorStages.count() + fCoverageStages.count();
151 for (int s = 0; s < totalStages; ++s) {
152 int covIdx = s - fColorStages.count();
153 const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
bsalomonf99f8842014-07-07 11:54:23 -0700154 const GrEffect* effect = stage.getEffect();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000155 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000156 // make sure that any attribute indices have the correct binding type, that the attrib
157 // type and effect's shader lang type are compatible, and that attributes shared by
158 // multiple effects use the same shader lang type.
159 const int* attributeIndices = stage.getVertexAttribIndices();
160 int numAttributes = stage.getVertexAttribIndexCount();
161 for (int i = 0; i < numAttributes; ++i) {
162 int attribIndex = attributeIndices[i];
bsalomon2ed5ef82014-07-07 08:44:05 -0700163 if (attribIndex >= fVACount ||
164 kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000165 return false;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000166 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000167
bsalomonf99f8842014-07-07 11:54:23 -0700168 GrSLType effectSLType = effect->vertexAttribType(i);
bsalomon2ed5ef82014-07-07 08:44:05 -0700169 GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000170 int slVecCount = GrSLTypeVectorCount(effectSLType);
171 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
172 if (slVecCount != attribVecCount ||
173 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
174 slTypes[attribIndex] != effectSLType)) {
175 return false;
176 }
177 slTypes[attribIndex] = effectSLType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000178 }
179 }
180
181 return true;
182}
183
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000184bool GrDrawState::willEffectReadDstColor() const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000185 if (!this->isColorWriteDisabled()) {
186 for (int s = 0; s < fColorStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700187 if (fColorStages[s].getEffect()->willReadDstColor()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000188 return true;
189 }
190 }
191 }
192 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700193 if (fCoverageStages[s].getEffect()->willReadDstColor()) {
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000194 return true;
195 }
196 }
197 return false;
198}
199
jvanverth@google.comcc782382013-01-28 20:39:48 +0000200////////////////////////////////////////////////////////////////////////////////
201
jvanverth@google.com054ae992013-04-01 20:06:51 +0000202bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000203 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000204 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000205 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000206 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000207 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000208 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000209 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000210 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211 color = this->getColor();
212 }
213
214 // Run through the color stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000215 for (int s = 0; s < fColorStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700216 const GrEffect* effect = fColorStages[s].getEffect();
217 effect->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000218 }
219
jvanverth@google.comcc782382013-01-28 20:39:48 +0000220 // Check whether coverage is treated as color. If so we run through the coverage computation.
221 if (this->isCoverageDrawing()) {
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000222 GrColor coverageColor = this->getCoverageColor();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000223 GrColor oldColor = color;
224 color = 0;
225 for (int c = 0; c < 4; ++c) {
226 if (validComponentFlags & (1 << c)) {
227 U8CPU a = (oldColor >> (c * 8)) & 0xff;
228 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
229 color |= (SkMulDiv255Round(a, b) << (c * 8));
230 }
231 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000232 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700233 const GrEffect* effect = fCoverageStages[s].getEffect();
234 effect->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000235 }
236 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000237 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000238}
239
jvanverth@google.com054ae992013-04-01 20:06:51 +0000240bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000241 // If we're drawing coverage directly then coverage is effectively treated as color.
242 if (this->isCoverageDrawing()) {
243 return true;
244 }
245
246 GrColor coverage;
247 uint32_t validComponentFlags;
248 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000249 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000250 validComponentFlags = 0;
251 } else {
bsalomon2ed5ef82014-07-07 08:44:05 -0700252 coverage = fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000253 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000254 }
255
256 // 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 +0000257 for (int s = 0; s < fCoverageStages.count(); ++s) {
bsalomonf99f8842014-07-07 11:54:23 -0700258 const GrEffect* effect = fCoverageStages[s].getEffect();
259 effect->getConstantColorComponents(&coverage, &validComponentFlags);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000260 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000261 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000262}
263
jvanverth@google.comcc782382013-01-28 20:39:48 +0000264////////////////////////////////////////////////////////////////////////////////
265
bsalomon@google.com2b446732013-02-12 16:47:41 +0000266// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
267// others will blend incorrectly.
268bool GrDrawState::canTweakAlphaForCoverage() const {
269 /*
270 The fractional coverage is f.
271 The src and dst coeffs are Cs and Cd.
272 The dst and src colors are S and D.
273 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
274 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
275 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
276 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
277 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
278 color by definition.
279 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700280 return kOne_GrBlendCoeff == fDstBlend ||
281 kISA_GrBlendCoeff == fDstBlend ||
282 kISC_GrBlendCoeff == fDstBlend ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000283 this->isCoverageDrawing();
284}
285
286GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
287 GrBlendCoeff* srcCoeff,
288 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000289
290 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
291 if (NULL == srcCoeff) {
292 srcCoeff = &bogusSrcCoeff;
293 }
294 *srcCoeff = this->getSrcBlendCoeff();
295
296 if (NULL == dstCoeff) {
297 dstCoeff = &bogusDstCoeff;
298 }
299 *dstCoeff = this->getDstBlendCoeff();
300
301 if (this->isColorWriteDisabled()) {
302 *srcCoeff = kZero_GrBlendCoeff;
303 *dstCoeff = kOne_GrBlendCoeff;
304 }
305
jvanverth@google.com054ae992013-04-01 20:06:51 +0000306 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000307 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
308 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
309 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
310 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
311
312 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000313 !this->hasCoverageVertexAttribute() &&
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000314 0 == this->getCoverageColor();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000315 // When coeffs are (0,1) there is no reason to draw at all, unless
316 // stenciling is enabled. Having color writes disabled is effectively
317 // (0,1). The same applies when coverage is known to be 0.
318 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
319 if (this->getStencil().doesWrite()) {
320 return kDisableBlend_BlendOptFlag |
commit-bot@chromium.orgbc98ff02013-08-15 18:16:41 +0000321 kEmitCoverage_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000322 } else {
323 return kSkipDraw_BlendOptFlag;
324 }
325 }
326
bsalomon@google.com4647f902013-03-26 14:45:27 +0000327 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000328 bool hasCoverage = forceCoverage ||
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000329 0xffffffff != this->getCoverageColor() ||
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000330 this->hasCoverageVertexAttribute() ||
331 fCoverageStages.count() > 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000332
333 // if we don't have coverage we can check whether the dst
334 // has to read at all. If not, we'll disable blending.
335 if (!hasCoverage) {
336 if (dstCoeffIsZero) {
337 if (kOne_GrBlendCoeff == *srcCoeff) {
338 // if there is no coverage and coeffs are (1,0) then we
339 // won't need to read the dst at all, it gets replaced by src
340 return kDisableBlend_BlendOptFlag;
341 } else if (kZero_GrBlendCoeff == *srcCoeff) {
342 // if the op is "clear" then we don't need to emit a color
343 // or blend, just write transparent black into the dst.
344 *srcCoeff = kOne_GrBlendCoeff;
345 *dstCoeff = kZero_GrBlendCoeff;
346 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
347 }
348 }
349 } else if (this->isCoverageDrawing()) {
350 // we have coverage but we aren't distinguishing it from alpha by request.
351 return kCoverageAsAlpha_BlendOptFlag;
352 } else {
353 // check whether coverage can be safely rolled into alpha
354 // of if we can skip color computation and just emit coverage
355 if (this->canTweakAlphaForCoverage()) {
356 return kCoverageAsAlpha_BlendOptFlag;
357 }
358 if (dstCoeffIsZero) {
359 if (kZero_GrBlendCoeff == *srcCoeff) {
360 // the source color is not included in the blend
361 // the dst coeff is effectively zero so blend works out to:
362 // (c)(0)D + (1-c)D = (1-c)D.
363 *dstCoeff = kISA_GrBlendCoeff;
364 return kEmitCoverage_BlendOptFlag;
365 } else if (srcAIsOne) {
366 // the dst coeff is effectively zero so blend works out to:
367 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
368 // If Sa is 1 then we can replace Sa with c
369 // and set dst coeff to 1-Sa.
370 *dstCoeff = kISA_GrBlendCoeff;
371 return kCoverageAsAlpha_BlendOptFlag;
372 }
373 } else if (dstCoeffIsOne) {
374 // the dst coeff is effectively one so blend works out to:
375 // cS + (c)(1)D + (1-c)D = cS + D.
376 *dstCoeff = kOne_GrBlendCoeff;
377 return kCoverageAsAlpha_BlendOptFlag;
378 }
379 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000380 if (kOne_GrBlendCoeff == *srcCoeff &&
381 kZero_GrBlendCoeff == *dstCoeff &&
382 this->willEffectReadDstColor()) {
383 // In this case the shader will fully resolve the color, coverage, and dst and we don't
384 // need blending.
385 return kDisableBlend_BlendOptFlag;
386 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000387 return kNone_BlendOpt;
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000392void GrDrawState::AutoViewMatrixRestore::restore() {
393 if (NULL != fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000394 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700395 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000396 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000397 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000398 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000399
400 int i = 0;
401 for (int s = 0; s < fNumColorStages; ++s, ++i) {
402 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
403 }
404 for (int s = 0; s < numCoverageStages; ++s, ++i) {
405 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000406 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000407 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000408 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000409}
410
411void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000412 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000413 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000414
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000415 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000416 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000417 return;
418 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000419 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000420
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000421 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700422 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000423
424 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000425 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000426}
427
bsalomon@google.com137f1342013-05-29 21:27:53 +0000428bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000429 this->restore();
430
bsalomon@google.com137f1342013-05-29 21:27:53 +0000431 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000432 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000433 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000434
bsalomon@google.com137f1342013-05-29 21:27:53 +0000435 if (drawState->getViewMatrix().isIdentity()) {
436 return true;
437 }
438
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000439 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000440 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700441 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000442 fDrawState = drawState;
443 fNumColorStages = 0;
444 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000445 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000446 return true;
447 } else {
448 SkMatrix inv;
449 if (!fViewMatrix.invert(&inv)) {
450 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000451 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700452 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000453 fDrawState = drawState;
454 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000455 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000456 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000457 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000458}
459
460void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
461 fSavedCoordChanges.reset(fDrawState->numTotalStages());
462 int i = 0;
463
464 fNumColorStages = fDrawState->numColorStages();
465 for (int s = 0; s < fNumColorStages; ++s, ++i) {
466 fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
467 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000468 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000469
470 int numCoverageStages = fDrawState->numCoverageStages();
471 for (int s = 0; s < numCoverageStages; ++s, ++i) {
472 fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
473 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
474 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000475}