blob: 8c2d75f0b502715d2d8d0e25411b08530d1b4671 [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
egdaniel915187b2014-12-05 12:58:28 -080054 if (!this->getXPFactory()->isEqual(*that.getXPFactory())) {
55 return false;
56 }
57
egdaniel89af44a2014-09-26 06:15:04 -070058 for (int i = 0; i < this->numColorStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070059 if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070060 explicitLocalCoords)) {
61 return false;
62 }
63 }
64 for (int i = 0; i < this->numCoverageStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070065 if (!GrFragmentStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070066 explicitLocalCoords)) {
67 return false;
68 }
69 }
70
egdaniel89af44a2014-09-26 06:15:04 -070071 return true;
72}
73
bsalomon8f727332014-08-05 07:50:06 -070074//////////////////////////////////////////////////////////////////////////////s
75
egdaniel69bb90c2014-11-11 07:32:45 -080076GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
bsalomon8f727332014-08-05 07:50:06 -070077 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
78 *this = state;
79 if (!preConcatMatrix.isIdentity()) {
egdaniel776bdbd2014-08-06 11:07:02 -070080 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070081 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070082 }
egdaniel776bdbd2014-08-06 11:07:02 -070083 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070084 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070085 }
bsalomon8f727332014-08-05 07:50:06 -070086 }
87}
88
89GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
bsalomonae59b772014-11-19 08:23:49 -080090 fRenderTarget.reset(SkSafeRef(that.fRenderTarget.get()));
bsalomon8f727332014-08-05 07:50:06 -070091 fColor = that.fColor;
92 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -070093 fSrcBlend = that.fSrcBlend;
94 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -070095 fBlendConstant = that.fBlendConstant;
96 fFlagBits = that.fFlagBits;
bsalomon8f727332014-08-05 07:50:06 -070097 fStencilSettings = that.fStencilSettings;
98 fCoverage = that.fCoverage;
99 fDrawFace = that.fDrawFace;
bsalomonae59b772014-11-19 08:23:49 -0800100 fGeometryProcessor.reset(SkSafeRef(that.fGeometryProcessor.get()));
egdaniel378092f2014-12-03 10:40:13 -0800101 fXPFactory.reset(SkRef(that.getXPFactory()));
egdaniel8cbf3d52014-08-21 06:27:22 -0700102 fColorStages = that.fColorStages;
103 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700104
bsalomon62c447d2014-08-08 08:08:50 -0700105 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700106
egdanielb6cbc382014-11-13 11:00:34 -0800107 fColorProcInfoValid = that.fColorProcInfoValid;
108 fCoverageProcInfoValid = that.fCoverageProcInfoValid;
109 if (fColorProcInfoValid) {
110 fColorProcInfo = that.fColorProcInfo;
111 }
112 if (fCoverageProcInfoValid) {
113 fCoverageProcInfo = that.fCoverageProcInfo;
114 }
bsalomon8f727332014-08-05 07:50:06 -0700115 return *this;
116}
117
118void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
119 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomonae59b772014-11-19 08:23:49 -0800120 fRenderTarget.reset(NULL);
bsalomon2a9ca782014-09-05 14:27:43 -0700121
joshualittbd769d02014-09-04 08:56:46 -0700122 fGeometryProcessor.reset(NULL);
egdanielc016fb82014-12-03 11:41:54 -0800123 fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
egdaniel8cbf3d52014-08-21 06:27:22 -0700124 fColorStages.reset();
125 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700126
bsalomon8f727332014-08-05 07:50:06 -0700127 fColor = 0xffffffff;
128 if (NULL == initialViewMatrix) {
129 fViewMatrix.reset();
130 } else {
131 fViewMatrix = *initialViewMatrix;
132 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700133 fSrcBlend = kOne_GrBlendCoeff;
134 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700135 fBlendConstant = 0x0;
136 fFlagBits = 0x0;
137 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700138 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700139 fDrawFace = kBoth_DrawFace;
140
bsalomon62c447d2014-08-08 08:08:50 -0700141 fHints = 0;
egdanielb6cbc382014-11-13 11:00:34 -0800142
143 fColorProcInfoValid = false;
144 fCoverageProcInfoValid = false;
bsalomon8f727332014-08-05 07:50:06 -0700145}
146
bsalomon@google.com137f1342013-05-29 21:27:53 +0000147bool GrDrawState::setIdentityViewMatrix() {
joshualitt4dd99882014-11-11 08:51:30 -0800148 if (this->numFragmentStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000149 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700150 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000151 // sad trombone sound
152 return false;
153 }
egdaniel776bdbd2014-08-06 11:07:02 -0700154 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700155 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000156 }
egdaniel776bdbd2014-08-06 11:07:02 -0700157 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700158 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000159 }
160 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700161 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000162 return true;
163}
164
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000165void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000166 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000167
joshualittbd769d02014-09-04 08:56:46 -0700168 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700169 fColorStages.reset();
170 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000171
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000172 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700173 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000174 }
175
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000176 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700177 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000178 }
179
egdaniel378092f2014-12-03 10:40:13 -0800180 fXPFactory.reset(SkRef(paint.getXPFactory()));
181
182 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000183 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000184
bsalomon2ed5ef82014-07-07 08:44:05 -0700185 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000186
187 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700188 fBlendConstant = 0x0;
189 fDrawFace = kBoth_DrawFace;
190 fStencilSettings.setDisabled();
bsalomon04ddf892014-11-19 12:36:22 -0800191 fFlagBits = 0;
bsalomon62c447d2014-08-08 08:08:50 -0700192 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000193
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000194 // Enable the clip bit
195 this->enableState(GrDrawState::kClip_StateBit);
196
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000197 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000198 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
199 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000200
joshualitt4052a8e2014-11-11 13:46:30 -0800201 this->setCoverage(0xFF);
egdanielb6cbc382014-11-13 11:00:34 -0800202 fColorProcInfoValid = false;
203 fCoverageProcInfoValid = false;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000204}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000205
206////////////////////////////////////////////////////////////////////////////////
207
bsalomon62c447d2014-08-08 08:08:50 -0700208bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
209 if (caps.dualSourceBlendingSupport()) {
210 return true;
211 }
212 // we can correctly apply coverage if a) we have dual source blending
213 // or b) one of our blend optimizations applies
214 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
215 GrBlendCoeff srcCoeff;
216 GrBlendCoeff dstCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800217 BlendOpt opt = this->getBlendOpt(true, &srcCoeff, &dstCoeff);
218 return GrDrawState::kNone_BlendOpt != opt ||
bsalomon62c447d2014-08-08 08:08:50 -0700219 (this->willEffectReadDstColor() &&
220 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
221}
222
egdaniel89af44a2014-09-26 06:15:04 -0700223bool GrDrawState::hasSolidCoverage() const {
224 // If we're drawing coverage directly then coverage is effectively treated as color.
225 if (this->isCoverageDrawing()) {
226 return true;
227 }
228
joshualitt4dd99882014-11-11 08:51:30 -0800229 if (this->numCoverageStages() > 0) {
230 return false;
231 }
232
egdanielb6cbc382014-11-13 11:00:34 -0800233 this->calcCoverageInvariantOutput();
234 return fCoverageProcInfo.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700235}
236
egdaniel21aed572014-08-26 12:24:06 -0700237//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238
egdaniel89af44a2014-09-26 06:15:04 -0700239bool GrDrawState::willEffectReadDstColor() const {
240 if (!this->isColorWriteDisabled()) {
egdanielb6cbc382014-11-13 11:00:34 -0800241 this->calcColorInvariantOutput();
242 if (fColorProcInfo.readsDst()) {
egdaniel89af44a2014-09-26 06:15:04 -0700243 return true;
244 }
245 }
egdanielb6cbc382014-11-13 11:00:34 -0800246 this->calcCoverageInvariantOutput();
247 return fCoverageProcInfo.readsDst();
egdaniel89af44a2014-09-26 06:15:04 -0700248}
249
egdaniel21aed572014-08-26 12:24:06 -0700250void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700251 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700252 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700253 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700254 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700255 } else {
joshualitta5305a12014-10-10 17:47:00 -0700256 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700257 fOriginalGPID);
258 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700259 }
joshualittbd769d02014-09-04 08:56:46 -0700260
egdaniel21aed572014-08-26 12:24:06 -0700261 int m = fDrawState->numColorStages() - fColorEffectCnt;
262 SkASSERT(m >= 0);
263 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000264
egdaniel21aed572014-08-26 12:24:06 -0700265 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
266 SkASSERT(n >= 0);
267 fDrawState->fCoverageStages.pop_back_n(n);
egdanielb6cbc382014-11-13 11:00:34 -0800268 if (m + n > 0) {
269 fDrawState->fColorProcInfoValid = false;
270 fDrawState->fCoverageProcInfoValid = false;
271 }
egdaniel21aed572014-08-26 12:24:06 -0700272 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000273 }
egdaniel21aed572014-08-26 12:24:06 -0700274 fDrawState = ds;
275 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700276 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700277 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700278 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700279 }
egdaniel21aed572014-08-26 12:24:06 -0700280 fColorEffectCnt = ds->numColorStages();
281 fCoverageEffectCnt = ds->numCoverageStages();
282 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
283 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000284}
285
jvanverth@google.comcc782382013-01-28 20:39:48 +0000286////////////////////////////////////////////////////////////////////////////////
287
egdaniel89af44a2014-09-26 06:15:04 -0700288// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
289// others will blend incorrectly.
290bool GrDrawState::canTweakAlphaForCoverage() const {
291 /*
292 The fractional coverage is f.
293 The src and dst coeffs are Cs and Cd.
294 The dst and src colors are S and D.
295 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
296 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
297 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
298 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
299 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
300 color by definition.
301 */
302 return kOne_GrBlendCoeff == fDstBlend ||
303 kISA_GrBlendCoeff == fDstBlend ||
304 kISC_GrBlendCoeff == fDstBlend ||
305 this->isCoverageDrawing();
306}
307
308////////////////////////////////////////////////////////////////////////////////
309
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000310void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700311 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000312 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700313 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000314 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000315 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000316 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000317
318 int i = 0;
319 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700320 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000321 }
322 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700323 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000324 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000325 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000326 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000327}
328
329void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000330 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000331 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000332
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000333 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000334 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000335 return;
336 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000337 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000338
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000339 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700340 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000341
342 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000343 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000344}
345
bsalomon@google.com137f1342013-05-29 21:27:53 +0000346bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000347 this->restore();
348
bsalomon@google.com137f1342013-05-29 21:27:53 +0000349 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000350 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000351 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000352
bsalomon@google.com137f1342013-05-29 21:27:53 +0000353 if (drawState->getViewMatrix().isIdentity()) {
354 return true;
355 }
356
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000357 fViewMatrix = drawState->getViewMatrix();
joshualitt4dd99882014-11-11 08:51:30 -0800358 if (0 == drawState->numFragmentStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700359 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000360 fDrawState = drawState;
361 fNumColorStages = 0;
362 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000363 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000364 return true;
365 } else {
366 SkMatrix inv;
367 if (!fViewMatrix.invert(&inv)) {
368 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000369 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700370 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000371 fDrawState = drawState;
372 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000373 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000374 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000375 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000376}
377
378void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
joshualitt4dd99882014-11-11 08:51:30 -0800379 fSavedCoordChanges.reset(fDrawState->numFragmentStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000380 int i = 0;
381
382 fNumColorStages = fDrawState->numColorStages();
383 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700384 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700385 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000386 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000387
388 int numCoverageStages = fDrawState->numCoverageStages();
389 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700390 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700391 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000392 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000393}
egdaniel21aed572014-08-26 12:24:06 -0700394
egdaniel170f90b2014-09-16 12:54:40 -0700395////////////////////////////////////////////////////////////////////////////////
396
egdaniel170f90b2014-09-16 12:54:40 -0700397GrDrawState::~GrDrawState() {
egdaniel170f90b2014-09-16 12:54:40 -0700398 SkASSERT(0 == fBlockEffectRemovalCnt);
399}
400
egdaniel89af44a2014-09-26 06:15:04 -0700401////////////////////////////////////////////////////////////////////////////////
402
bsalomon04ddf892014-11-19 12:36:22 -0800403GrDrawState::BlendOpt GrDrawState::getBlendOpt(bool forceCoverage,
404 GrBlendCoeff* srcCoeff,
405 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700406 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
407 if (NULL == srcCoeff) {
408 srcCoeff = &bogusSrcCoeff;
409 }
410 if (NULL == dstCoeff) {
411 dstCoeff = &bogusDstCoeff;
412 }
413
414 *srcCoeff = this->getSrcBlendCoeff();
415 *dstCoeff = this->getDstBlendCoeff();
416
417 if (this->isColorWriteDisabled()) {
418 *srcCoeff = kZero_GrBlendCoeff;
419 *dstCoeff = kOne_GrBlendCoeff;
420 }
421
422 bool srcAIsOne = this->srcAlphaWillBeOne();
423 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
424 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
425 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
426 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
427
428 // When coeffs are (0,1) there is no reason to draw at all, unless
429 // stenciling is enabled. Having color writes disabled is effectively
430 // (0,1).
431 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
432 if (this->getStencil().doesWrite()) {
bsalomon04ddf892014-11-19 12:36:22 -0800433 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700434 } else {
435 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800436 return kSkipDraw_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700437 }
438 }
439
440 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
441
442 // if we don't have coverage we can check whether the dst
443 // has to read at all. If not, we'll disable blending.
444 if (!hasCoverage) {
445 if (dstCoeffIsZero) {
446 if (kOne_GrBlendCoeff == *srcCoeff) {
447 // if there is no coverage and coeffs are (1,0) then we
448 // won't need to read the dst at all, it gets replaced by src
449 *dstCoeff = kZero_GrBlendCoeff;
450 return kNone_BlendOpt;
451 } else if (kZero_GrBlendCoeff == *srcCoeff) {
452 // if the op is "clear" then we don't need to emit a color
453 // or blend, just write transparent black into the dst.
454 *srcCoeff = kOne_GrBlendCoeff;
455 *dstCoeff = kZero_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800456 return kEmitTransBlack_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700457 }
458 }
459 } else if (this->isCoverageDrawing()) {
460 // we have coverage but we aren't distinguishing it from alpha by request.
bsalomon04ddf892014-11-19 12:36:22 -0800461 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700462 } else {
463 // check whether coverage can be safely rolled into alpha
464 // of if we can skip color computation and just emit coverage
465 if (this->canTweakAlphaForCoverage()) {
bsalomon04ddf892014-11-19 12:36:22 -0800466 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700467 }
468 if (dstCoeffIsZero) {
469 if (kZero_GrBlendCoeff == *srcCoeff) {
470 // the source color is not included in the blend
471 // the dst coeff is effectively zero so blend works out to:
472 // (c)(0)D + (1-c)D = (1-c)D.
473 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800474 return kEmitCoverage_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700475 } else if (srcAIsOne) {
476 // the dst coeff is effectively zero so blend works out to:
477 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
478 // If Sa is 1 then we can replace Sa with c
479 // and set dst coeff to 1-Sa.
480 *dstCoeff = kISA_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800481 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700482 }
483 } else if (dstCoeffIsOne) {
484 // the dst coeff is effectively one so blend works out to:
485 // cS + (c)(1)D + (1-c)D = cS + D.
486 *dstCoeff = kOne_GrBlendCoeff;
bsalomon04ddf892014-11-19 12:36:22 -0800487 return kCoverageAsAlpha_BlendOpt;
egdaniel89af44a2014-09-26 06:15:04 -0700488 }
489 }
490
491 return kNone_BlendOpt;
492}
493
egdaniel89af44a2014-09-26 06:15:04 -0700494bool GrDrawState::srcAlphaWillBeOne() const {
egdanielb6cbc382014-11-13 11:00:34 -0800495 this->calcColorInvariantOutput();
egdaniel89af44a2014-09-26 06:15:04 -0700496 if (this->isCoverageDrawing()) {
egdanielb6cbc382014-11-13 11:00:34 -0800497 this->calcCoverageInvariantOutput();
498 return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700499 }
egdanielb6cbc382014-11-13 11:00:34 -0800500 return fColorProcInfo.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700501}
502
egdanielcd8b6302014-11-11 14:46:05 -0800503bool GrDrawState::willBlendWithDst() const {
504 if (!this->hasSolidCoverage()) {
505 return true;
506 }
507
egdanielb1cff032014-11-13 06:19:25 -0800508 if (this->willEffectReadDstColor()) {
509 return true;
egdanielcd8b6302014-11-11 14:46:05 -0800510 }
egdanielb1cff032014-11-13 06:19:25 -0800511
512 if (GrBlendCoeffRefsDst(this->getSrcBlendCoeff())) {
513 return true;
514 }
515
516 GrBlendCoeff dstCoeff = this->getDstBlendCoeff();
517 if (!(kZero_GrBlendCoeff == dstCoeff ||
518 (kISA_GrBlendCoeff == dstCoeff && this->srcAlphaWillBeOne()))) {
egdanielcd8b6302014-11-11 14:46:05 -0800519 return true;
520 }
521
522 return false;
523}
524
egdanielb6cbc382014-11-13 11:00:34 -0800525void GrDrawState::calcColorInvariantOutput() const {
526 if (!fColorProcInfoValid) {
527 GrColor color;
528 GrColorComponentFlags flags;
529 if (this->hasColorVertexAttribute()) {
530 if (fHints & kVertexColorsAreOpaque_Hint) {
531 flags = kA_GrColorComponentFlag;
532 color = 0xFF << GrColor_SHIFT_A;
533 } else {
534 flags = static_cast<GrColorComponentFlags>(0);
535 color = 0;
536 }
537 } else {
538 flags = kRGBA_GrColorComponentFlags;
539 color = this->getColor();
540 }
541 fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(),
542 color, flags, false);
543 fColorProcInfoValid = true;
544 }
545}
546
547void GrDrawState::calcCoverageInvariantOutput() const {
548 if (!fCoverageProcInfoValid) {
549 GrColor color;
550 GrColorComponentFlags flags;
551 // Check if per-vertex or constant color may have partial alpha
552 if (this->hasCoverageVertexAttribute()) {
553 flags = static_cast<GrColorComponentFlags>(0);
554 color = 0;
555 } else {
556 flags = kRGBA_GrColorComponentFlags;
557 color = this->getCoverageColor();
558 }
559 fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
560 color, flags, true, fGeometryProcessor.get());
561 fCoverageProcInfoValid = true;
562 }
563}
564