blob: 0fd098740c5337dc704014ae86dd81c9673df603 [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"
egdaniel3658f382014-09-15 07:01:59 -07009
egdanielb1cff032014-11-13 06:19:25 -080010#include "GrBlend.h"
egdaniel3658f382014-09-15 07:01:59 -070011#include "GrOptDrawState.h"
12#include "GrPaint.h"
egdanielb6cbc382014-11-13 11:00:34 -080013#include "GrProcOptInfo.h"
egdaniel378092f2014-12-03 10:40:13 -080014#include "GrXferProcessor.h"
15#include "effects/GrPorterDuffXferProcessor.h"
egdaniel3658f382014-09-15 07:01:59 -070016
egdaniel378092f2014-12-03 10:40:13 -080017///////////////////////////////////////////////////////////////////////////////
egdaniel3658f382014-09-15 07:01:59 -070018
egdaniel89af44a2014-09-26 06:15:04 -070019bool GrDrawState::isEqual(const GrDrawState& that) const {
20 bool usingVertexColors = this->hasColorVertexAttribute();
21 if (!usingVertexColors && this->fColor != that.fColor) {
22 return false;
23 }
24
25 if (this->getRenderTarget() != that.getRenderTarget() ||
26 this->fColorStages.count() != that.fColorStages.count() ||
27 this->fCoverageStages.count() != that.fCoverageStages.count() ||
28 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
29 this->fSrcBlend != that.fSrcBlend ||
30 this->fDstBlend != that.fDstBlend ||
31 this->fBlendConstant != that.fBlendConstant ||
32 this->fFlagBits != that.fFlagBits ||
egdaniel89af44a2014-09-26 06:15:04 -070033 this->fStencilSettings != that.fStencilSettings ||
34 this->fDrawFace != that.fDrawFace) {
35 return false;
36 }
37
38 bool usingVertexCoverage = this->hasCoverageVertexAttribute();
39 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
40 return false;
41 }
42
43 bool explicitLocalCoords = this->hasLocalCoordAttribute();
44 if (this->hasGeometryProcessor()) {
45 if (!that.hasGeometryProcessor()) {
46 return false;
joshualitta5305a12014-10-10 17:47:00 -070047 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -070048 return false;
49 }
50 } else if (that.hasGeometryProcessor()) {
51 return false;
52 }
53
54 for (int i = 0; i < this->numColorStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070055 if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070056 explicitLocalCoords)) {
57 return false;
58 }
59 }
60 for (int i = 0; i < this->numCoverageStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070061 if (!GrFragmentStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070062 explicitLocalCoords)) {
63 return false;
64 }
65 }
66
egdaniel89af44a2014-09-26 06:15:04 -070067 return true;
68}
69
bsalomon8f727332014-08-05 07:50:06 -070070//////////////////////////////////////////////////////////////////////////////s
71
egdaniel69bb90c2014-11-11 07:32:45 -080072GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
bsalomon8f727332014-08-05 07:50:06 -070073 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
74 *this = state;
75 if (!preConcatMatrix.isIdentity()) {
egdaniel776bdbd2014-08-06 11:07:02 -070076 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070077 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070078 }
egdaniel776bdbd2014-08-06 11:07:02 -070079 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070080 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070081 }
bsalomon8f727332014-08-05 07:50:06 -070082 }
83}
84
85GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
bsalomonae59b772014-11-19 08:23:49 -080086 fRenderTarget.reset(SkSafeRef(that.fRenderTarget.get()));
bsalomon8f727332014-08-05 07:50:06 -070087 fColor = that.fColor;
88 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -070089 fSrcBlend = that.fSrcBlend;
90 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -070091 fBlendConstant = that.fBlendConstant;
92 fFlagBits = that.fFlagBits;
bsalomon8f727332014-08-05 07:50:06 -070093 fStencilSettings = that.fStencilSettings;
94 fCoverage = that.fCoverage;
95 fDrawFace = that.fDrawFace;
bsalomonae59b772014-11-19 08:23:49 -080096 fGeometryProcessor.reset(SkSafeRef(that.fGeometryProcessor.get()));
egdaniel378092f2014-12-03 10:40:13 -080097 fXPFactory.reset(SkRef(that.getXPFactory()));
egdaniel8cbf3d52014-08-21 06:27:22 -070098 fColorStages = that.fColorStages;
99 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700100
bsalomon62c447d2014-08-08 08:08:50 -0700101 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700102
egdanielb6cbc382014-11-13 11:00:34 -0800103 fColorProcInfoValid = that.fColorProcInfoValid;
104 fCoverageProcInfoValid = that.fCoverageProcInfoValid;
105 if (fColorProcInfoValid) {
106 fColorProcInfo = that.fColorProcInfo;
107 }
108 if (fCoverageProcInfoValid) {
109 fCoverageProcInfo = that.fCoverageProcInfo;
110 }
bsalomon8f727332014-08-05 07:50:06 -0700111 return *this;
112}
113
114void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
115 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomonae59b772014-11-19 08:23:49 -0800116 fRenderTarget.reset(NULL);
bsalomon2a9ca782014-09-05 14:27:43 -0700117
joshualittbd769d02014-09-04 08:56:46 -0700118 fGeometryProcessor.reset(NULL);
egdaniel378092f2014-12-03 10:40:13 -0800119 fXPFactory.reset(GrPorterDuffXPFactory::Create(kOne_GrBlendCoeff,
120 kZero_GrBlendCoeff));
egdaniel8cbf3d52014-08-21 06:27:22 -0700121 fColorStages.reset();
122 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700123
bsalomon8f727332014-08-05 07:50:06 -0700124 fColor = 0xffffffff;
125 if (NULL == initialViewMatrix) {
126 fViewMatrix.reset();
127 } else {
128 fViewMatrix = *initialViewMatrix;
129 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700130 fSrcBlend = kOne_GrBlendCoeff;
131 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700132 fBlendConstant = 0x0;
133 fFlagBits = 0x0;
134 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700135 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700136 fDrawFace = kBoth_DrawFace;
137
bsalomon62c447d2014-08-08 08:08:50 -0700138 fHints = 0;
egdanielb6cbc382014-11-13 11:00:34 -0800139
140 fColorProcInfoValid = false;
141 fCoverageProcInfoValid = false;
bsalomon8f727332014-08-05 07:50:06 -0700142}
143
bsalomon@google.com137f1342013-05-29 21:27:53 +0000144bool GrDrawState::setIdentityViewMatrix() {
joshualitt4dd99882014-11-11 08:51:30 -0800145 if (this->numFragmentStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000146 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700147 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000148 // sad trombone sound
149 return false;
150 }
egdaniel776bdbd2014-08-06 11:07:02 -0700151 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700152 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000153 }
egdaniel776bdbd2014-08-06 11:07:02 -0700154 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700155 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000156 }
157 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700158 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000159 return true;
160}
161
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000162void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000163 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000164
joshualittbd769d02014-09-04 08:56:46 -0700165 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700166 fColorStages.reset();
167 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000168
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000169 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700170 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000171 }
172
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000173 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700174 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000175 }
176
egdaniel378092f2014-12-03 10:40:13 -0800177 fXPFactory.reset(SkRef(paint.getXPFactory()));
178
179 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000180 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000181
bsalomon2ed5ef82014-07-07 08:44:05 -0700182 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000183
184 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700185 fBlendConstant = 0x0;
186 fDrawFace = kBoth_DrawFace;
187 fStencilSettings.setDisabled();
bsalomon04ddf892014-11-19 12:36:22 -0800188 fFlagBits = 0;
bsalomon62c447d2014-08-08 08:08:50 -0700189 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000190
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000191 // Enable the clip bit
192 this->enableState(GrDrawState::kClip_StateBit);
193
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000194 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000195 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
196 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000197
joshualitt4052a8e2014-11-11 13:46:30 -0800198 this->setCoverage(0xFF);
egdanielb6cbc382014-11-13 11:00:34 -0800199 fColorProcInfoValid = false;
200 fCoverageProcInfoValid = false;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000201}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000202
203////////////////////////////////////////////////////////////////////////////////
204
bsalomon62c447d2014-08-08 08:08:50 -0700205bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
206 if (caps.dualSourceBlendingSupport()) {
207 return true;
208 }
209 // we can correctly apply coverage if a) we have dual source blending
210 // or b) one of our blend optimizations applies
211 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
212 GrBlendCoeff srcCoeff;
213 GrBlendCoeff dstCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800214 BlendOpt opt = this->getBlendOpt(true, &srcCoeff, &dstCoeff);
215 return GrDrawState::kNone_BlendOpt != opt ||
bsalomon62c447d2014-08-08 08:08:50 -0700216 (this->willEffectReadDstColor() &&
217 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
218}
219
egdaniel89af44a2014-09-26 06:15:04 -0700220bool GrDrawState::hasSolidCoverage() const {
221 // If we're drawing coverage directly then coverage is effectively treated as color.
222 if (this->isCoverageDrawing()) {
223 return true;
224 }
225
joshualitt4dd99882014-11-11 08:51:30 -0800226 if (this->numCoverageStages() > 0) {
227 return false;
228 }
229
egdanielb6cbc382014-11-13 11:00:34 -0800230 this->calcCoverageInvariantOutput();
231 return fCoverageProcInfo.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700232}
233
egdaniel21aed572014-08-26 12:24:06 -0700234//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000235
egdaniel89af44a2014-09-26 06:15:04 -0700236bool GrDrawState::willEffectReadDstColor() const {
237 if (!this->isColorWriteDisabled()) {
egdanielb6cbc382014-11-13 11:00:34 -0800238 this->calcColorInvariantOutput();
239 if (fColorProcInfo.readsDst()) {
egdaniel89af44a2014-09-26 06:15:04 -0700240 return true;
241 }
242 }
egdanielb6cbc382014-11-13 11:00:34 -0800243 this->calcCoverageInvariantOutput();
244 return fCoverageProcInfo.readsDst();
egdaniel89af44a2014-09-26 06:15:04 -0700245}
246
egdaniel21aed572014-08-26 12:24:06 -0700247void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700248 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700249 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700250 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700251 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700252 } else {
joshualitta5305a12014-10-10 17:47:00 -0700253 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700254 fOriginalGPID);
255 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700256 }
joshualittbd769d02014-09-04 08:56:46 -0700257
egdaniel21aed572014-08-26 12:24:06 -0700258 int m = fDrawState->numColorStages() - fColorEffectCnt;
259 SkASSERT(m >= 0);
260 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261
egdaniel21aed572014-08-26 12:24:06 -0700262 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
263 SkASSERT(n >= 0);
264 fDrawState->fCoverageStages.pop_back_n(n);
egdanielb6cbc382014-11-13 11:00:34 -0800265 if (m + n > 0) {
266 fDrawState->fColorProcInfoValid = false;
267 fDrawState->fCoverageProcInfoValid = false;
268 }
egdaniel21aed572014-08-26 12:24:06 -0700269 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000270 }
egdaniel21aed572014-08-26 12:24:06 -0700271 fDrawState = ds;
272 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700273 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700274 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700275 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700276 }
egdaniel21aed572014-08-26 12:24:06 -0700277 fColorEffectCnt = ds->numColorStages();
278 fCoverageEffectCnt = ds->numCoverageStages();
279 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
280 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000281}
282
jvanverth@google.comcc782382013-01-28 20:39:48 +0000283////////////////////////////////////////////////////////////////////////////////
284
egdaniel89af44a2014-09-26 06:15:04 -0700285// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
286// others will blend incorrectly.
287bool GrDrawState::canTweakAlphaForCoverage() const {
288 /*
289 The fractional coverage is f.
290 The src and dst coeffs are Cs and Cd.
291 The dst and src colors are S and D.
292 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
293 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
294 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
295 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
296 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
297 color by definition.
298 */
299 return kOne_GrBlendCoeff == fDstBlend ||
300 kISA_GrBlendCoeff == fDstBlend ||
301 kISC_GrBlendCoeff == fDstBlend ||
302 this->isCoverageDrawing();
303}
304
305////////////////////////////////////////////////////////////////////////////////
306
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000307void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700308 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000309 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700310 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000311 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000312 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000313 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000314
315 int i = 0;
316 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700317 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000318 }
319 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700320 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000321 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000322 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000323 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000324}
325
326void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000327 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000328 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000329
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000330 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000331 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000332 return;
333 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000334 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000335
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000336 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700337 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000338
339 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000340 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000341}
342
bsalomon@google.com137f1342013-05-29 21:27:53 +0000343bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000344 this->restore();
345
bsalomon@google.com137f1342013-05-29 21:27:53 +0000346 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000347 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000348 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000349
bsalomon@google.com137f1342013-05-29 21:27:53 +0000350 if (drawState->getViewMatrix().isIdentity()) {
351 return true;
352 }
353
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000354 fViewMatrix = drawState->getViewMatrix();
joshualitt4dd99882014-11-11 08:51:30 -0800355 if (0 == drawState->numFragmentStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700356 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000357 fDrawState = drawState;
358 fNumColorStages = 0;
359 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000360 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000361 return true;
362 } else {
363 SkMatrix inv;
364 if (!fViewMatrix.invert(&inv)) {
365 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000366 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700367 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000368 fDrawState = drawState;
369 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000370 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000371 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000372 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000373}
374
375void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
joshualitt4dd99882014-11-11 08:51:30 -0800376 fSavedCoordChanges.reset(fDrawState->numFragmentStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000377 int i = 0;
378
379 fNumColorStages = fDrawState->numColorStages();
380 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700381 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700382 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000383 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000384
385 int numCoverageStages = fDrawState->numCoverageStages();
386 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700387 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700388 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000389 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000390}
egdaniel21aed572014-08-26 12:24:06 -0700391
egdaniel170f90b2014-09-16 12:54:40 -0700392////////////////////////////////////////////////////////////////////////////////
393
egdaniel170f90b2014-09-16 12:54:40 -0700394GrDrawState::~GrDrawState() {
egdaniel170f90b2014-09-16 12:54:40 -0700395 SkASSERT(0 == fBlockEffectRemovalCnt);
396}
397
egdaniel89af44a2014-09-26 06:15:04 -0700398////////////////////////////////////////////////////////////////////////////////
399
bsalomon04ddf892014-11-19 12:36:22 -0800400GrDrawState::BlendOpt GrDrawState::getBlendOpt(bool forceCoverage,
401 GrBlendCoeff* srcCoeff,
402 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700403 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
404 if (NULL == srcCoeff) {
405 srcCoeff = &bogusSrcCoeff;
406 }
407 if (NULL == dstCoeff) {
408 dstCoeff = &bogusDstCoeff;
409 }
410
411 *srcCoeff = this->getSrcBlendCoeff();
412 *dstCoeff = this->getDstBlendCoeff();
413
414 if (this->isColorWriteDisabled()) {
415 *srcCoeff = kZero_GrBlendCoeff;
416 *dstCoeff = kOne_GrBlendCoeff;
417 }
418
419 bool srcAIsOne = this->srcAlphaWillBeOne();
420 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
421 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
422 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
423 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
424
425 // When coeffs are (0,1) there is no reason to draw at all, unless
426 // stenciling is enabled. Having color writes disabled is effectively
427 // (0,1).
428 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
429 if (this->getStencil().doesWrite()) {
bsalomon04ddf892014-11-19 12:36:22 -0800430 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700431 } else {
432 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800433 return kSkipDraw_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700434 }
435 }
436
437 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
438
439 // if we don't have coverage we can check whether the dst
440 // has to read at all. If not, we'll disable blending.
441 if (!hasCoverage) {
442 if (dstCoeffIsZero) {
443 if (kOne_GrBlendCoeff == *srcCoeff) {
444 // if there is no coverage and coeffs are (1,0) then we
445 // won't need to read the dst at all, it gets replaced by src
446 *dstCoeff = kZero_GrBlendCoeff;
447 return kNone_BlendOpt;
448 } else if (kZero_GrBlendCoeff == *srcCoeff) {
449 // if the op is "clear" then we don't need to emit a color
450 // or blend, just write transparent black into the dst.
451 *srcCoeff = kOne_GrBlendCoeff;
452 *dstCoeff = kZero_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800453 return kEmitTransBlack_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700454 }
455 }
456 } else if (this->isCoverageDrawing()) {
457 // we have coverage but we aren't distinguishing it from alpha by request.
bsalomon04ddf892014-11-19 12:36:22 -0800458 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700459 } else {
460 // check whether coverage can be safely rolled into alpha
461 // of if we can skip color computation and just emit coverage
462 if (this->canTweakAlphaForCoverage()) {
bsalomon04ddf892014-11-19 12:36:22 -0800463 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700464 }
465 if (dstCoeffIsZero) {
466 if (kZero_GrBlendCoeff == *srcCoeff) {
467 // the source color is not included in the blend
468 // the dst coeff is effectively zero so blend works out to:
469 // (c)(0)D + (1-c)D = (1-c)D.
470 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800471 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700472 } else if (srcAIsOne) {
473 // the dst coeff is effectively zero so blend works out to:
474 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
475 // If Sa is 1 then we can replace Sa with c
476 // and set dst coeff to 1-Sa.
477 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800478 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700479 }
480 } else if (dstCoeffIsOne) {
481 // the dst coeff is effectively one so blend works out to:
482 // cS + (c)(1)D + (1-c)D = cS + D.
483 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800484 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700485 }
486 }
487
488 return kNone_BlendOpt;
489}
490
egdaniel89af44a2014-09-26 06:15:04 -0700491bool GrDrawState::srcAlphaWillBeOne() const {
egdanielb6cbc382014-11-13 11:00:34 -0800492 this->calcColorInvariantOutput();
egdaniel89af44a2014-09-26 06:15:04 -0700493 if (this->isCoverageDrawing()) {
egdanielb6cbc382014-11-13 11:00:34 -0800494 this->calcCoverageInvariantOutput();
495 return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700496 }
egdanielb6cbc382014-11-13 11:00:34 -0800497 return fColorProcInfo.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700498}
499
egdanielcd8b6302014-11-11 14:46:05 -0800500bool GrDrawState::willBlendWithDst() const {
501 if (!this->hasSolidCoverage()) {
502 return true;
503 }
504
egdanielb1cff032014-11-13 06:19:25 -0800505 if (this->willEffectReadDstColor()) {
506 return true;
egdanielcd8b6302014-11-11 14:46:05 -0800507 }
egdanielb1cff032014-11-13 06:19:25 -0800508
509 if (GrBlendCoeffRefsDst(this->getSrcBlendCoeff())) {
510 return true;
511 }
512
513 GrBlendCoeff dstCoeff = this->getDstBlendCoeff();
514 if (!(kZero_GrBlendCoeff == dstCoeff ||
515 (kISA_GrBlendCoeff == dstCoeff && this->srcAlphaWillBeOne()))) {
egdanielcd8b6302014-11-11 14:46:05 -0800516 return true;
517 }
518
519 return false;
520}
521
egdanielb6cbc382014-11-13 11:00:34 -0800522void GrDrawState::calcColorInvariantOutput() const {
523 if (!fColorProcInfoValid) {
524 GrColor color;
525 GrColorComponentFlags flags;
526 if (this->hasColorVertexAttribute()) {
527 if (fHints & kVertexColorsAreOpaque_Hint) {
528 flags = kA_GrColorComponentFlag;
529 color = 0xFF << GrColor_SHIFT_A;
530 } else {
531 flags = static_cast<GrColorComponentFlags>(0);
532 color = 0;
533 }
534 } else {
535 flags = kRGBA_GrColorComponentFlags;
536 color = this->getColor();
537 }
538 fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(),
539 color, flags, false);
540 fColorProcInfoValid = true;
541 }
542}
543
544void GrDrawState::calcCoverageInvariantOutput() const {
545 if (!fCoverageProcInfoValid) {
546 GrColor color;
547 GrColorComponentFlags flags;
548 // Check if per-vertex or constant color may have partial alpha
549 if (this->hasCoverageVertexAttribute()) {
550 flags = static_cast<GrColorComponentFlags>(0);
551 color = 0;
552 } else {
553 flags = kRGBA_GrColorComponentFlags;
554 color = this->getCoverageColor();
555 }
556 fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
557 color, flags, true, fGeometryProcessor.get());
558 fCoverageProcInfoValid = true;
559 }
560}
561