blob: ffec6627ca4c9687b473faf6a09ce7b21bf36da0 [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"
bsalomon62c447d2014-08-08 08:08:50 -070010#include "GrDrawTargetCaps.h"
bsalomon@google.comaf84e742012-10-05 13:23:24 +000011
bsalomon8f727332014-08-05 07:50:06 -070012//////////////////////////////////////////////////////////////////////////////s
13
14GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070015 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -070016
egdaniel21aed572014-08-26 12:24:06 -070017 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -070018 return kIncompatible_CombinedState;
19 }
20
egdaniel21aed572014-08-26 12:24:06 -070021 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
22 // is equivalent for both a and b
23 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -070024 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
25 // if the opaqueness affects the ability to get color/coverage blending correct then we
26 // don't combine the draw states.
27 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
28 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
29 if (aIsOpaque != bIsOpaque) {
30 const GrDrawState* opaque;
31 const GrDrawState* nonOpaque;
32 if (aIsOpaque) {
33 opaque = &a;
34 nonOpaque = &b;
35 } else {
36 opaque = &b;
37 nonOpaque = &a;
38 }
39 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
40 SkASSERT(!nonOpaque->hasSolidCoverage());
41 if (!nonOpaque->couldApplyCoverage(caps)) {
42 return kIncompatible_CombinedState;
43 }
44 }
45 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
46 }
47 }
bsalomon8f727332014-08-05 07:50:06 -070048 return kAOrB_CombinedState;
49}
50
bsalomon8f727332014-08-05 07:50:06 -070051//////////////////////////////////////////////////////////////////////////////s
52
53GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
54 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
55 *this = state;
56 if (!preConcatMatrix.isIdentity()) {
joshualittbd769d02014-09-04 08:56:46 -070057 if (this->hasGeometryProcessor()) {
58 fGeometryProcessor->localCoordChange(preConcatMatrix);
59 }
egdaniel776bdbd2014-08-06 11:07:02 -070060 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070061 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070062 }
egdaniel776bdbd2014-08-06 11:07:02 -070063 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070064 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070065 }
66 this->invalidateBlendOptFlags();
67 }
68}
69
70GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
71 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -070072 SkASSERT(!that.fRenderTarget.ownsPendingIO());
73 SkASSERT(!this->fRenderTarget.ownsPendingIO());
74 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -070075 fColor = that.fColor;
76 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -070077 fSrcBlend = that.fSrcBlend;
78 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -070079 fBlendConstant = that.fBlendConstant;
80 fFlagBits = that.fFlagBits;
81 fVACount = that.fVACount;
82 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -070083 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -070084 fStencilSettings = that.fStencilSettings;
85 fCoverage = that.fCoverage;
86 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -070087 if (that.hasGeometryProcessor()) {
88 fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*that.fGeometryProcessor.get())));
89 } else {
90 fGeometryProcessor.reset(NULL);
91 }
egdaniel8cbf3d52014-08-21 06:27:22 -070092 fColorStages = that.fColorStages;
93 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -070094 fOptSrcBlend = that.fOptSrcBlend;
95 fOptDstBlend = that.fOptDstBlend;
96 fBlendOptFlags = that.fBlendOptFlags;
97
bsalomon62c447d2014-08-08 08:08:50 -070098 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -070099
bsalomon8f727332014-08-05 07:50:06 -0700100 memcpy(fFixedFunctionVertexAttribIndices,
101 that.fFixedFunctionVertexAttribIndices,
102 sizeof(fFixedFunctionVertexAttribIndices));
103 return *this;
104}
105
106void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
107 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700108 SkASSERT(!fRenderTarget.ownsPendingIO());
109
joshualittbd769d02014-09-04 08:56:46 -0700110 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700111 fColorStages.reset();
112 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700113
bsalomon2a9ca782014-09-05 14:27:43 -0700114 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700115
116 this->setDefaultVertexAttribs();
117
118 fColor = 0xffffffff;
119 if (NULL == initialViewMatrix) {
120 fViewMatrix.reset();
121 } else {
122 fViewMatrix = *initialViewMatrix;
123 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700124 fSrcBlend = kOne_GrBlendCoeff;
125 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700126 fBlendConstant = 0x0;
127 fFlagBits = 0x0;
128 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700129 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700130 fDrawFace = kBoth_DrawFace;
131
bsalomon62c447d2014-08-08 08:08:50 -0700132 fHints = 0;
133
bsalomon8f727332014-08-05 07:50:06 -0700134 this->invalidateBlendOptFlags();
135}
136
bsalomon@google.com137f1342013-05-29 21:27:53 +0000137bool GrDrawState::setIdentityViewMatrix() {
egdaniel776bdbd2014-08-06 11:07:02 -0700138 if (this->numTotalStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000139 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700140 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000141 // sad trombone sound
142 return false;
143 }
joshualittbd769d02014-09-04 08:56:46 -0700144 if (this->hasGeometryProcessor()) {
145 fGeometryProcessor->localCoordChange(invVM);
146 }
egdaniel776bdbd2014-08-06 11:07:02 -0700147 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700148 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000149 }
egdaniel776bdbd2014-08-06 11:07:02 -0700150 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700151 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000152 }
153 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700154 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000155 return true;
156}
157
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000158void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000159 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000160
joshualittbd769d02014-09-04 08:56:46 -0700161 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700162 fColorStages.reset();
163 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000164
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000165 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700166 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000167 }
168
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000169 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700170 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000171 }
172
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000173 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000174
bsalomon2ed5ef82014-07-07 08:44:05 -0700175 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000176
177 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700178 fBlendConstant = 0x0;
179 fDrawFace = kBoth_DrawFace;
180 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000181 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700182 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000183
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000184 // Enable the clip bit
185 this->enableState(GrDrawState::kClip_StateBit);
186
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000187 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000188 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
189 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000190
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000191 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000192 this->setCoverage(paint.getCoverage());
egdaniel9514d242014-07-18 06:15:43 -0700193 this->invalidateBlendOptFlags();
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000194}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000195
196////////////////////////////////////////////////////////////////////////////////
197
egdaniel7b3d5ee2014-08-28 05:41:14 -0700198static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000199 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000200#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000201 uint32_t overlapCheck = 0;
egdaniel21aed572014-08-26 12:24:06 -0700202 SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000203 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000204 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700205 size_t attribOffset = attribs[index].fOffset;
206 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000207 size_t dwordCount = attribSize >> 2;
208 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700209 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000210 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000211 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700212 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700213#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000214}
215
216////////////////////////////////////////////////////////////////////////////////
217
egdaniel7b3d5ee2014-08-28 05:41:14 -0700218void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
219 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000220 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000221
bsalomon2ed5ef82014-07-07 08:44:05 -0700222 fVAPtr = attribs;
223 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700224 fVAStride = stride;
225 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000226
227 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700228 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000229 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700230 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000231#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000232 uint32_t overlapCheck = 0;
233#endif
234 for (int i = 0; i < count; ++i) {
235 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
236 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700237 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000238 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000239 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700240 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000241 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000242#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000243 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
244 uint32_t mask = (1 << dwordCount)-1;
245 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000246 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000247 overlapCheck |= (mask << offsetShift);
248#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000249 }
egdaniel9514d242014-07-18 06:15:43 -0700250 this->invalidateBlendOptFlags();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000251 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700252 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000253}
254
255////////////////////////////////////////////////////////////////////////////////
256
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000257void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000258 static const GrVertexAttrib kPositionAttrib =
259 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000260
bsalomon2ed5ef82014-07-07 08:44:05 -0700261 fVAPtr = &kPositionAttrib;
262 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700263 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000264
jvanverth@google.com054ae992013-04-01 20:06:51 +0000265 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700266 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000267 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700268 sizeof(fFixedFunctionVertexAttribIndices));
269 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel9514d242014-07-18 06:15:43 -0700270 this->invalidateBlendOptFlags();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000271}
272
273////////////////////////////////////////////////////////////////////////////////
274
bsalomon62c447d2014-08-08 08:08:50 -0700275bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
276 if (caps.dualSourceBlendingSupport()) {
277 return true;
278 }
279 // we can correctly apply coverage if a) we have dual source blending
280 // or b) one of our blend optimizations applies
281 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
282 GrBlendCoeff srcCoeff;
283 GrBlendCoeff dstCoeff;
egdaniel21aed572014-08-26 12:24:06 -0700284 GrRODrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
285 return GrRODrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700286 (this->willEffectReadDstColor() &&
287 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
288}
289
egdaniel21aed572014-08-26 12:24:06 -0700290//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000291
egdaniel21aed572014-08-26 12:24:06 -0700292GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
293 GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700294 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700295 fDrawState = drawState;
296 fVAPtr = drawState->fVAPtr;
297 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700298 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700299 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000300}
301
egdaniel21aed572014-08-26 12:24:06 -0700302//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000303
egdaniel21aed572014-08-26 12:24:06 -0700304void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700305 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700306 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700307 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700308 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700309 } else {
310 SkASSERT(fDrawState->getGeometryProcessor()->getEffect()->getUniqueID() ==
311 fOriginalGPID);
312 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700313 }
joshualittbd769d02014-09-04 08:56:46 -0700314
egdaniel21aed572014-08-26 12:24:06 -0700315 int m = fDrawState->numColorStages() - fColorEffectCnt;
316 SkASSERT(m >= 0);
317 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000318
egdaniel21aed572014-08-26 12:24:06 -0700319 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
320 SkASSERT(n >= 0);
321 fDrawState->fCoverageStages.pop_back_n(n);
322 if (m + n > 0) {
323 fDrawState->invalidateBlendOptFlags();
324 }
325 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000326 }
egdaniel21aed572014-08-26 12:24:06 -0700327 fDrawState = ds;
328 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700329 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700330 if (NULL != ds->getGeometryProcessor()) {
bsalomon52e9d632014-09-05 12:23:12 -0700331 fOriginalGPID = ds->getGeometryProcessor()->getEffect()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700332 }
egdaniel21aed572014-08-26 12:24:06 -0700333 fColorEffectCnt = ds->numColorStages();
334 fCoverageEffectCnt = ds->numCoverageStages();
335 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
336 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000337}
338
jvanverth@google.comcc782382013-01-28 20:39:48 +0000339////////////////////////////////////////////////////////////////////////////////
340
egdaniel21aed572014-08-26 12:24:06 -0700341GrRODrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
342 GrBlendCoeff* srcCoeff,
343 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000344 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
345 if (NULL == srcCoeff) {
346 srcCoeff = &bogusSrcCoeff;
347 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000348 if (NULL == dstCoeff) {
349 dstCoeff = &bogusDstCoeff;
350 }
egdaniel9514d242014-07-18 06:15:43 -0700351
352 if (forceCoverage) {
353 return this->calcBlendOpts(true, srcCoeff, dstCoeff);
354 }
355
356 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
357 *srcCoeff = fOptSrcBlend;
358 *dstCoeff = fOptDstBlend;
359 return fBlendOptFlags;
360 }
361
362 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
363 fOptSrcBlend = *srcCoeff;
364 fOptDstBlend = *dstCoeff;
365
366 return fBlendOptFlags;
367}
368
egdaniel21aed572014-08-26 12:24:06 -0700369GrRODrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
370 GrBlendCoeff* srcCoeff,
371 GrBlendCoeff* dstCoeff) const {
egdaniel9514d242014-07-18 06:15:43 -0700372 *srcCoeff = this->getSrcBlendCoeff();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000373 *dstCoeff = this->getDstBlendCoeff();
374
375 if (this->isColorWriteDisabled()) {
376 *srcCoeff = kZero_GrBlendCoeff;
377 *dstCoeff = kOne_GrBlendCoeff;
378 }
379
jvanverth@google.com054ae992013-04-01 20:06:51 +0000380 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000381 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
382 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
383 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
384 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
385
bsalomon@google.com2b446732013-02-12 16:47:41 +0000386 // When coeffs are (0,1) there is no reason to draw at all, unless
387 // stenciling is enabled. Having color writes disabled is effectively
bsalomon62c447d2014-08-08 08:08:50 -0700388 // (0,1).
389 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000390 if (this->getStencil().doesWrite()) {
egdaniel0f1a7c42014-07-30 13:18:32 -0700391 return kEmitCoverage_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000392 } else {
393 return kSkipDraw_BlendOptFlag;
394 }
395 }
396
bsalomon62c447d2014-08-08 08:08:50 -0700397 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000398
399 // if we don't have coverage we can check whether the dst
400 // has to read at all. If not, we'll disable blending.
401 if (!hasCoverage) {
402 if (dstCoeffIsZero) {
403 if (kOne_GrBlendCoeff == *srcCoeff) {
404 // if there is no coverage and coeffs are (1,0) then we
405 // won't need to read the dst at all, it gets replaced by src
egdaniel0f1a7c42014-07-30 13:18:32 -0700406 *dstCoeff = kZero_GrBlendCoeff;
407 return kNone_BlendOpt;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000408 } else if (kZero_GrBlendCoeff == *srcCoeff) {
409 // if the op is "clear" then we don't need to emit a color
410 // or blend, just write transparent black into the dst.
411 *srcCoeff = kOne_GrBlendCoeff;
412 *dstCoeff = kZero_GrBlendCoeff;
egdaniel0f1a7c42014-07-30 13:18:32 -0700413 return kEmitTransBlack_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000414 }
415 }
416 } else if (this->isCoverageDrawing()) {
417 // we have coverage but we aren't distinguishing it from alpha by request.
418 return kCoverageAsAlpha_BlendOptFlag;
419 } else {
420 // check whether coverage can be safely rolled into alpha
421 // of if we can skip color computation and just emit coverage
422 if (this->canTweakAlphaForCoverage()) {
423 return kCoverageAsAlpha_BlendOptFlag;
424 }
425 if (dstCoeffIsZero) {
426 if (kZero_GrBlendCoeff == *srcCoeff) {
427 // the source color is not included in the blend
428 // the dst coeff is effectively zero so blend works out to:
429 // (c)(0)D + (1-c)D = (1-c)D.
430 *dstCoeff = kISA_GrBlendCoeff;
431 return kEmitCoverage_BlendOptFlag;
432 } else if (srcAIsOne) {
433 // the dst coeff is effectively zero so blend works out to:
434 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
435 // If Sa is 1 then we can replace Sa with c
436 // and set dst coeff to 1-Sa.
437 *dstCoeff = kISA_GrBlendCoeff;
438 return kCoverageAsAlpha_BlendOptFlag;
439 }
440 } else if (dstCoeffIsOne) {
441 // the dst coeff is effectively one so blend works out to:
442 // cS + (c)(1)D + (1-c)D = cS + D.
443 *dstCoeff = kOne_GrBlendCoeff;
444 return kCoverageAsAlpha_BlendOptFlag;
445 }
446 }
egdaniel0f1a7c42014-07-30 13:18:32 -0700447
bsalomon@google.com2b446732013-02-12 16:47:41 +0000448 return kNone_BlendOpt;
449}
450
451////////////////////////////////////////////////////////////////////////////////
452
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000453void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700454 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000455 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700456 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000457 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000458 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000459 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000460
461 int i = 0;
joshualittbd769d02014-09-04 08:56:46 -0700462 if (fHasGeometryProcessor) {
463 SkASSERT(fDrawState->hasGeometryProcessor());
464 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
465 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000466 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700467 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000468 }
469 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700470 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000471 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000472 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000473 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000474}
475
476void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000477 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000478 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000479
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000480 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000481 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000482 return;
483 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000484 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000485
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000486 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700487 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000488
489 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000490 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491}
492
bsalomon@google.com137f1342013-05-29 21:27:53 +0000493bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000494 this->restore();
495
bsalomon@google.com137f1342013-05-29 21:27:53 +0000496 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000497 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000498 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000499
bsalomon@google.com137f1342013-05-29 21:27:53 +0000500 if (drawState->getViewMatrix().isIdentity()) {
501 return true;
502 }
503
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000504 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000505 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700506 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000507 fDrawState = drawState;
joshualittbd769d02014-09-04 08:56:46 -0700508 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000509 fNumColorStages = 0;
510 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000511 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000512 return true;
513 } else {
514 SkMatrix inv;
515 if (!fViewMatrix.invert(&inv)) {
516 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000517 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700518 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000519 fDrawState = drawState;
520 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000521 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000522 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000523 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000524}
525
526void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
527 fSavedCoordChanges.reset(fDrawState->numTotalStages());
528 int i = 0;
529
joshualittbd769d02014-09-04 08:56:46 -0700530 fHasGeometryProcessor = false;
531 if (fDrawState->hasGeometryProcessor()) {
532 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
533 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
534 fHasGeometryProcessor = true;
535 }
536
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000537 fNumColorStages = fDrawState->numColorStages();
538 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700539 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700540 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000541 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000542
543 int numCoverageStages = fDrawState->numCoverageStages();
544 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700545 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700546 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000547 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000548}
egdaniel21aed572014-08-26 12:24:06 -0700549
550bool GrDrawState::srcAlphaWillBeOne() const {
551 uint32_t validComponentFlags;
552 GrColor color;
553 // Check if per-vertex or constant color may have partial alpha
554 if (this->hasColorVertexAttribute()) {
555 if (fHints & kVertexColorsAreOpaque_Hint) {
556 validComponentFlags = kA_GrColorComponentFlag;
557 color = 0xFF << GrColor_SHIFT_A;
558 } else {
559 validComponentFlags = 0;
560 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
561 }
562 } else {
563 validComponentFlags = kRGBA_GrColorComponentFlags;
564 color = this->getColor();
565 }
566
567 // Run through the color stages
568 for (int s = 0; s < this->numColorStages(); ++s) {
569 const GrEffect* effect = this->getColorStage(s).getEffect();
570 effect->getConstantColorComponents(&color, &validComponentFlags);
571 }
572
573 // Check whether coverage is treated as color. If so we run through the coverage computation.
574 if (this->isCoverageDrawing()) {
575 // The shader generated for coverage drawing runs the full coverage computation and then
576 // makes the shader output be the multiplication of color and coverage. We mirror that here.
577 GrColor coverage;
578 uint32_t coverageComponentFlags;
579 if (this->hasCoverageVertexAttribute()) {
580 coverageComponentFlags = 0;
581 coverage = 0; // suppresses any warnings.
582 } else {
583 coverageComponentFlags = kRGBA_GrColorComponentFlags;
584 coverage = this->getCoverageColor();
585 }
586
587 // Run through the coverage stages
joshualittbd769d02014-09-04 08:56:46 -0700588 if (this->hasGeometryProcessor()) {
589 const GrEffect* effect = fGeometryProcessor->getEffect();
590 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
591 }
egdaniel21aed572014-08-26 12:24:06 -0700592 for (int s = 0; s < this->numCoverageStages(); ++s) {
593 const GrEffect* effect = this->getCoverageStage(s).getEffect();
594 effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
595 }
596
597 // Since the shader will multiply coverage and color, the only way the final A==1 is if
598 // coverage and color both have A==1.
599 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
600 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
601
602 }
603
604 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
605}
606
607////////////////////////////////////////////////////////////////////////////////
608
609bool GrDrawState::canIgnoreColorAttribute() const {
610 if (fBlendOptFlags & kInvalid_BlendOptFlag) {
611 this->getBlendOpts();
612 }
613 return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag |
614 GrRODrawState::kEmitCoverage_BlendOptFlag));
615}