blob: db70bfaaa2351c6ecb964c103f2f3291c261c1a0 [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);
egdanielc016fb82014-12-03 11:41:54 -0800119 fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
egdaniel8cbf3d52014-08-21 06:27:22 -0700120 fColorStages.reset();
121 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700122
bsalomon8f727332014-08-05 07:50:06 -0700123 fColor = 0xffffffff;
124 if (NULL == initialViewMatrix) {
125 fViewMatrix.reset();
126 } else {
127 fViewMatrix = *initialViewMatrix;
128 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700129 fSrcBlend = kOne_GrBlendCoeff;
130 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700131 fBlendConstant = 0x0;
132 fFlagBits = 0x0;
133 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700134 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700135 fDrawFace = kBoth_DrawFace;
136
bsalomon62c447d2014-08-08 08:08:50 -0700137 fHints = 0;
egdanielb6cbc382014-11-13 11:00:34 -0800138
139 fColorProcInfoValid = false;
140 fCoverageProcInfoValid = false;
bsalomon8f727332014-08-05 07:50:06 -0700141}
142
bsalomon@google.com137f1342013-05-29 21:27:53 +0000143bool GrDrawState::setIdentityViewMatrix() {
joshualitt4dd99882014-11-11 08:51:30 -0800144 if (this->numFragmentStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000145 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700146 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000147 // sad trombone sound
148 return false;
149 }
egdaniel776bdbd2014-08-06 11:07:02 -0700150 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700151 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000152 }
egdaniel776bdbd2014-08-06 11:07:02 -0700153 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700154 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000155 }
156 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700157 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000158 return true;
159}
160
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000161void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000162 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000163
joshualittbd769d02014-09-04 08:56:46 -0700164 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700165 fColorStages.reset();
166 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000167
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000168 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700169 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000170 }
171
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000172 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700173 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000174 }
175
egdaniel378092f2014-12-03 10:40:13 -0800176 fXPFactory.reset(SkRef(paint.getXPFactory()));
177
178 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000179 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000180
bsalomon2ed5ef82014-07-07 08:44:05 -0700181 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000182
183 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700184 fBlendConstant = 0x0;
185 fDrawFace = kBoth_DrawFace;
186 fStencilSettings.setDisabled();
bsalomon04ddf892014-11-19 12:36:22 -0800187 fFlagBits = 0;
bsalomon62c447d2014-08-08 08:08:50 -0700188 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000189
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000190 // Enable the clip bit
191 this->enableState(GrDrawState::kClip_StateBit);
192
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000193 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000194 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
195 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000196
joshualitt4052a8e2014-11-11 13:46:30 -0800197 this->setCoverage(0xFF);
egdanielb6cbc382014-11-13 11:00:34 -0800198 fColorProcInfoValid = false;
199 fCoverageProcInfoValid = false;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000200}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000201
202////////////////////////////////////////////////////////////////////////////////
203
bsalomon62c447d2014-08-08 08:08:50 -0700204bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
205 if (caps.dualSourceBlendingSupport()) {
206 return true;
207 }
208 // we can correctly apply coverage if a) we have dual source blending
209 // or b) one of our blend optimizations applies
210 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
211 GrBlendCoeff srcCoeff;
212 GrBlendCoeff dstCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800213 BlendOpt opt = this->getBlendOpt(true, &srcCoeff, &dstCoeff);
214 return GrDrawState::kNone_BlendOpt != opt ||
bsalomon62c447d2014-08-08 08:08:50 -0700215 (this->willEffectReadDstColor() &&
216 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
217}
218
egdaniel89af44a2014-09-26 06:15:04 -0700219bool GrDrawState::hasSolidCoverage() const {
220 // If we're drawing coverage directly then coverage is effectively treated as color.
221 if (this->isCoverageDrawing()) {
222 return true;
223 }
224
joshualitt4dd99882014-11-11 08:51:30 -0800225 if (this->numCoverageStages() > 0) {
226 return false;
227 }
228
egdanielb6cbc382014-11-13 11:00:34 -0800229 this->calcCoverageInvariantOutput();
230 return fCoverageProcInfo.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700231}
232
egdaniel21aed572014-08-26 12:24:06 -0700233//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000234
egdaniel89af44a2014-09-26 06:15:04 -0700235bool GrDrawState::willEffectReadDstColor() const {
236 if (!this->isColorWriteDisabled()) {
egdanielb6cbc382014-11-13 11:00:34 -0800237 this->calcColorInvariantOutput();
238 if (fColorProcInfo.readsDst()) {
egdaniel89af44a2014-09-26 06:15:04 -0700239 return true;
240 }
241 }
egdanielb6cbc382014-11-13 11:00:34 -0800242 this->calcCoverageInvariantOutput();
243 return fCoverageProcInfo.readsDst();
egdaniel89af44a2014-09-26 06:15:04 -0700244}
245
egdaniel21aed572014-08-26 12:24:06 -0700246void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700247 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700248 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700249 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700250 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700251 } else {
joshualitta5305a12014-10-10 17:47:00 -0700252 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700253 fOriginalGPID);
254 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700255 }
joshualittbd769d02014-09-04 08:56:46 -0700256
egdaniel21aed572014-08-26 12:24:06 -0700257 int m = fDrawState->numColorStages() - fColorEffectCnt;
258 SkASSERT(m >= 0);
259 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000260
egdaniel21aed572014-08-26 12:24:06 -0700261 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
262 SkASSERT(n >= 0);
263 fDrawState->fCoverageStages.pop_back_n(n);
egdanielb6cbc382014-11-13 11:00:34 -0800264 if (m + n > 0) {
265 fDrawState->fColorProcInfoValid = false;
266 fDrawState->fCoverageProcInfoValid = false;
267 }
egdaniel21aed572014-08-26 12:24:06 -0700268 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000269 }
egdaniel21aed572014-08-26 12:24:06 -0700270 fDrawState = ds;
271 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700272 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700273 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700274 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700275 }
egdaniel21aed572014-08-26 12:24:06 -0700276 fColorEffectCnt = ds->numColorStages();
277 fCoverageEffectCnt = ds->numCoverageStages();
278 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
279 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000280}
281
jvanverth@google.comcc782382013-01-28 20:39:48 +0000282////////////////////////////////////////////////////////////////////////////////
283
egdaniel89af44a2014-09-26 06:15:04 -0700284// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
285// others will blend incorrectly.
286bool GrDrawState::canTweakAlphaForCoverage() const {
287 /*
288 The fractional coverage is f.
289 The src and dst coeffs are Cs and Cd.
290 The dst and src colors are S and D.
291 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
292 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
293 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
294 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
295 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
296 color by definition.
297 */
298 return kOne_GrBlendCoeff == fDstBlend ||
299 kISA_GrBlendCoeff == fDstBlend ||
300 kISC_GrBlendCoeff == fDstBlend ||
301 this->isCoverageDrawing();
302}
303
304////////////////////////////////////////////////////////////////////////////////
305
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000306void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700307 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000308 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700309 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000310 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000311 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000312 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000313
314 int i = 0;
315 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700316 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000317 }
318 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700319 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000320 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000321 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000322 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000323}
324
325void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000326 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000327 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000328
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000329 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000330 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000331 return;
332 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000333 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000334
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000335 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700336 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000337
338 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000339 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000340}
341
bsalomon@google.com137f1342013-05-29 21:27:53 +0000342bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000343 this->restore();
344
bsalomon@google.com137f1342013-05-29 21:27:53 +0000345 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000346 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000347 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000348
bsalomon@google.com137f1342013-05-29 21:27:53 +0000349 if (drawState->getViewMatrix().isIdentity()) {
350 return true;
351 }
352
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000353 fViewMatrix = drawState->getViewMatrix();
joshualitt4dd99882014-11-11 08:51:30 -0800354 if (0 == drawState->numFragmentStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700355 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000356 fDrawState = drawState;
357 fNumColorStages = 0;
358 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000359 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000360 return true;
361 } else {
362 SkMatrix inv;
363 if (!fViewMatrix.invert(&inv)) {
364 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000365 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700366 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000367 fDrawState = drawState;
368 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000369 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000370 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000371 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000372}
373
374void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
joshualitt4dd99882014-11-11 08:51:30 -0800375 fSavedCoordChanges.reset(fDrawState->numFragmentStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000376 int i = 0;
377
378 fNumColorStages = fDrawState->numColorStages();
379 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700380 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700381 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000382 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000383
384 int numCoverageStages = fDrawState->numCoverageStages();
385 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700386 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700387 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000388 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000389}
egdaniel21aed572014-08-26 12:24:06 -0700390
egdaniel170f90b2014-09-16 12:54:40 -0700391////////////////////////////////////////////////////////////////////////////////
392
egdaniel170f90b2014-09-16 12:54:40 -0700393GrDrawState::~GrDrawState() {
egdaniel170f90b2014-09-16 12:54:40 -0700394 SkASSERT(0 == fBlockEffectRemovalCnt);
395}
396
egdaniel89af44a2014-09-26 06:15:04 -0700397////////////////////////////////////////////////////////////////////////////////
398
bsalomon04ddf892014-11-19 12:36:22 -0800399GrDrawState::BlendOpt GrDrawState::getBlendOpt(bool forceCoverage,
400 GrBlendCoeff* srcCoeff,
401 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700402 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
403 if (NULL == srcCoeff) {
404 srcCoeff = &bogusSrcCoeff;
405 }
406 if (NULL == dstCoeff) {
407 dstCoeff = &bogusDstCoeff;
408 }
409
410 *srcCoeff = this->getSrcBlendCoeff();
411 *dstCoeff = this->getDstBlendCoeff();
412
413 if (this->isColorWriteDisabled()) {
414 *srcCoeff = kZero_GrBlendCoeff;
415 *dstCoeff = kOne_GrBlendCoeff;
416 }
417
418 bool srcAIsOne = this->srcAlphaWillBeOne();
419 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
420 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
421 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
422 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
423
424 // When coeffs are (0,1) there is no reason to draw at all, unless
425 // stenciling is enabled. Having color writes disabled is effectively
426 // (0,1).
427 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
428 if (this->getStencil().doesWrite()) {
bsalomon04ddf892014-11-19 12:36:22 -0800429 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700430 } else {
431 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800432 return kSkipDraw_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700433 }
434 }
435
436 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
437
438 // if we don't have coverage we can check whether the dst
439 // has to read at all. If not, we'll disable blending.
440 if (!hasCoverage) {
441 if (dstCoeffIsZero) {
442 if (kOne_GrBlendCoeff == *srcCoeff) {
443 // if there is no coverage and coeffs are (1,0) then we
444 // won't need to read the dst at all, it gets replaced by src
445 *dstCoeff = kZero_GrBlendCoeff;
446 return kNone_BlendOpt;
447 } else if (kZero_GrBlendCoeff == *srcCoeff) {
448 // if the op is "clear" then we don't need to emit a color
449 // or blend, just write transparent black into the dst.
450 *srcCoeff = kOne_GrBlendCoeff;
451 *dstCoeff = kZero_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800452 return kEmitTransBlack_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700453 }
454 }
455 } else if (this->isCoverageDrawing()) {
456 // we have coverage but we aren't distinguishing it from alpha by request.
bsalomon04ddf892014-11-19 12:36:22 -0800457 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700458 } else {
459 // check whether coverage can be safely rolled into alpha
460 // of if we can skip color computation and just emit coverage
461 if (this->canTweakAlphaForCoverage()) {
bsalomon04ddf892014-11-19 12:36:22 -0800462 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700463 }
464 if (dstCoeffIsZero) {
465 if (kZero_GrBlendCoeff == *srcCoeff) {
466 // the source color is not included in the blend
467 // the dst coeff is effectively zero so blend works out to:
468 // (c)(0)D + (1-c)D = (1-c)D.
469 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800470 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700471 } else if (srcAIsOne) {
472 // the dst coeff is effectively zero so blend works out to:
473 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
474 // If Sa is 1 then we can replace Sa with c
475 // and set dst coeff to 1-Sa.
476 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800477 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700478 }
479 } else if (dstCoeffIsOne) {
480 // the dst coeff is effectively one so blend works out to:
481 // cS + (c)(1)D + (1-c)D = cS + D.
482 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800483 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700484 }
485 }
486
487 return kNone_BlendOpt;
488}
489
egdaniel89af44a2014-09-26 06:15:04 -0700490bool GrDrawState::srcAlphaWillBeOne() const {
egdanielb6cbc382014-11-13 11:00:34 -0800491 this->calcColorInvariantOutput();
egdaniel89af44a2014-09-26 06:15:04 -0700492 if (this->isCoverageDrawing()) {
egdanielb6cbc382014-11-13 11:00:34 -0800493 this->calcCoverageInvariantOutput();
494 return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700495 }
egdanielb6cbc382014-11-13 11:00:34 -0800496 return fColorProcInfo.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700497}
498
egdanielcd8b6302014-11-11 14:46:05 -0800499bool GrDrawState::willBlendWithDst() const {
500 if (!this->hasSolidCoverage()) {
501 return true;
502 }
503
egdanielb1cff032014-11-13 06:19:25 -0800504 if (this->willEffectReadDstColor()) {
505 return true;
egdanielcd8b6302014-11-11 14:46:05 -0800506 }
egdanielb1cff032014-11-13 06:19:25 -0800507
508 if (GrBlendCoeffRefsDst(this->getSrcBlendCoeff())) {
509 return true;
510 }
511
512 GrBlendCoeff dstCoeff = this->getDstBlendCoeff();
513 if (!(kZero_GrBlendCoeff == dstCoeff ||
514 (kISA_GrBlendCoeff == dstCoeff && this->srcAlphaWillBeOne()))) {
egdanielcd8b6302014-11-11 14:46:05 -0800515 return true;
516 }
517
518 return false;
519}
520
egdanielb6cbc382014-11-13 11:00:34 -0800521void GrDrawState::calcColorInvariantOutput() const {
522 if (!fColorProcInfoValid) {
523 GrColor color;
524 GrColorComponentFlags flags;
525 if (this->hasColorVertexAttribute()) {
526 if (fHints & kVertexColorsAreOpaque_Hint) {
527 flags = kA_GrColorComponentFlag;
528 color = 0xFF << GrColor_SHIFT_A;
529 } else {
530 flags = static_cast<GrColorComponentFlags>(0);
531 color = 0;
532 }
533 } else {
534 flags = kRGBA_GrColorComponentFlags;
535 color = this->getColor();
536 }
537 fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(),
538 color, flags, false);
539 fColorProcInfoValid = true;
540 }
541}
542
543void GrDrawState::calcCoverageInvariantOutput() const {
544 if (!fCoverageProcInfoValid) {
545 GrColor color;
546 GrColorComponentFlags flags;
547 // Check if per-vertex or constant color may have partial alpha
548 if (this->hasCoverageVertexAttribute()) {
549 flags = static_cast<GrColorComponentFlags>(0);
550 color = 0;
551 } else {
552 flags = kRGBA_GrColorComponentFlags;
553 color = this->getCoverageColor();
554 }
555 fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
556 color, flags, true, fGeometryProcessor.get());
557 fCoverageProcInfoValid = true;
558 }
559}
560