blob: 87269658184b963c8abfb2ea62a095d1a89bb80d [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
egdaniel3658f382014-09-15 07:01:59 -070010#include "GrOptDrawState.h"
11#include "GrPaint.h"
12
13//////////////////////////////////////////////////////////////////////////////s
14
egdanielc0648242014-09-22 13:17:02 -070015GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const {
16 if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
egdaniel170f90b2014-09-16 12:54:40 -070017 GrBlendCoeff srcCoeff;
18 GrBlendCoeff dstCoeff;
19 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
egdanielc0648242014-09-22 13:17:02 -070020 fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
21 fCachedCapsID = caps.getUniqueID();
egdaniel3658f382014-09-15 07:01:59 -070022 } else {
egdaniel170f90b2014-09-16 12:54:40 -070023#ifdef SK_DEBUG
24 GrBlendCoeff srcCoeff;
25 GrBlendCoeff dstCoeff;
26 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
egdanielc0648242014-09-22 13:17:02 -070027 SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
egdaniel170f90b2014-09-16 12:54:40 -070028#endif
egdaniel3658f382014-09-15 07:01:59 -070029 }
30 fCachedOptState->ref();
31 return fCachedOptState;
32}
bsalomon@google.comaf84e742012-10-05 13:23:24 +000033
bsalomon8f727332014-08-05 07:50:06 -070034//////////////////////////////////////////////////////////////////////////////s
35
36GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070037 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -070038
egdaniel21aed572014-08-26 12:24:06 -070039 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -070040 return kIncompatible_CombinedState;
41 }
42
egdaniel21aed572014-08-26 12:24:06 -070043 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
44 // is equivalent for both a and b
45 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -070046 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
47 // if the opaqueness affects the ability to get color/coverage blending correct then we
48 // don't combine the draw states.
49 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
50 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
51 if (aIsOpaque != bIsOpaque) {
52 const GrDrawState* opaque;
53 const GrDrawState* nonOpaque;
54 if (aIsOpaque) {
55 opaque = &a;
56 nonOpaque = &b;
57 } else {
58 opaque = &b;
59 nonOpaque = &a;
60 }
61 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
62 SkASSERT(!nonOpaque->hasSolidCoverage());
63 if (!nonOpaque->couldApplyCoverage(caps)) {
64 return kIncompatible_CombinedState;
65 }
66 }
67 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
68 }
69 }
bsalomon8f727332014-08-05 07:50:06 -070070 return kAOrB_CombinedState;
71}
72
bsalomon8f727332014-08-05 07:50:06 -070073//////////////////////////////////////////////////////////////////////////////s
74
egdaniel3658f382014-09-15 07:01:59 -070075GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
76 : fCachedOptState(NULL) {
bsalomon8f727332014-08-05 07:50:06 -070077 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
78 *this = state;
79 if (!preConcatMatrix.isIdentity()) {
joshualittbd769d02014-09-04 08:56:46 -070080 if (this->hasGeometryProcessor()) {
81 fGeometryProcessor->localCoordChange(preConcatMatrix);
82 }
egdaniel776bdbd2014-08-06 11:07:02 -070083 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070084 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070085 }
egdaniel776bdbd2014-08-06 11:07:02 -070086 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -070087 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -070088 }
egdaniel3658f382014-09-15 07:01:59 -070089 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -070090 }
91}
92
93GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
94 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -070095 SkASSERT(!that.fRenderTarget.ownsPendingIO());
96 SkASSERT(!this->fRenderTarget.ownsPendingIO());
97 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -070098 fColor = that.fColor;
99 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -0700100 fSrcBlend = that.fSrcBlend;
101 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -0700102 fBlendConstant = that.fBlendConstant;
103 fFlagBits = that.fFlagBits;
104 fVACount = that.fVACount;
105 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700106 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -0700107 fStencilSettings = that.fStencilSettings;
108 fCoverage = that.fCoverage;
109 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -0700110 if (that.hasGeometryProcessor()) {
111 fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*that.fGeometryProcessor.get())));
112 } else {
113 fGeometryProcessor.reset(NULL);
114 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700115 fColorStages = that.fColorStages;
116 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700117
bsalomon62c447d2014-08-08 08:08:50 -0700118 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700119
egdaniel3658f382014-09-15 07:01:59 -0700120 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
121
bsalomon8f727332014-08-05 07:50:06 -0700122 memcpy(fFixedFunctionVertexAttribIndices,
123 that.fFixedFunctionVertexAttribIndices,
124 sizeof(fFixedFunctionVertexAttribIndices));
125 return *this;
126}
127
128void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
129 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700130 SkASSERT(!fRenderTarget.ownsPendingIO());
131
joshualittbd769d02014-09-04 08:56:46 -0700132 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700133 fColorStages.reset();
134 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700135
bsalomon2a9ca782014-09-05 14:27:43 -0700136 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700137
138 this->setDefaultVertexAttribs();
139
140 fColor = 0xffffffff;
141 if (NULL == initialViewMatrix) {
142 fViewMatrix.reset();
143 } else {
144 fViewMatrix = *initialViewMatrix;
145 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700146 fSrcBlend = kOne_GrBlendCoeff;
147 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700148 fBlendConstant = 0x0;
149 fFlagBits = 0x0;
150 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700151 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700152 fDrawFace = kBoth_DrawFace;
153
bsalomon62c447d2014-08-08 08:08:50 -0700154 fHints = 0;
155
egdaniel3658f382014-09-15 07:01:59 -0700156 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700157}
158
bsalomon@google.com137f1342013-05-29 21:27:53 +0000159bool GrDrawState::setIdentityViewMatrix() {
egdaniel776bdbd2014-08-06 11:07:02 -0700160 if (this->numTotalStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000161 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700162 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000163 // sad trombone sound
164 return false;
165 }
joshualittbd769d02014-09-04 08:56:46 -0700166 if (this->hasGeometryProcessor()) {
167 fGeometryProcessor->localCoordChange(invVM);
168 }
egdaniel776bdbd2014-08-06 11:07:02 -0700169 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700170 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000171 }
egdaniel776bdbd2014-08-06 11:07:02 -0700172 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700173 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000174 }
175 }
egdaniel3658f382014-09-15 07:01:59 -0700176 this->invalidateOptState();
bsalomon2ed5ef82014-07-07 08:44:05 -0700177 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000178 return true;
179}
180
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000181void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000182 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000183
joshualittbd769d02014-09-04 08:56:46 -0700184 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700185 fColorStages.reset();
186 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000187
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000188 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700189 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000190 }
191
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000192 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700193 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000194 }
195
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000196 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000197
bsalomon2ed5ef82014-07-07 08:44:05 -0700198 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000199
200 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700201 fBlendConstant = 0x0;
202 fDrawFace = kBoth_DrawFace;
203 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000204 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700205 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000206
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000207 // Enable the clip bit
208 this->enableState(GrDrawState::kClip_StateBit);
209
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000210 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000211 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
212 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000213
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000214 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000215 this->setCoverage(paint.getCoverage());
egdaniel3658f382014-09-15 07:01:59 -0700216 this->invalidateOptState();
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000217}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000218
219////////////////////////////////////////////////////////////////////////////////
220
egdaniel7b3d5ee2014-08-28 05:41:14 -0700221static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000222 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000223#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000224 uint32_t overlapCheck = 0;
egdaniel21aed572014-08-26 12:24:06 -0700225 SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000226 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000227 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700228 size_t attribOffset = attribs[index].fOffset;
229 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000230 size_t dwordCount = attribSize >> 2;
231 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700232 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000233 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000234 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700235 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700236#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000237}
238
239////////////////////////////////////////////////////////////////////////////////
240
egdaniel7b3d5ee2014-08-28 05:41:14 -0700241void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
242 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000243 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000244
bsalomon2ed5ef82014-07-07 08:44:05 -0700245 fVAPtr = attribs;
246 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700247 fVAStride = stride;
248 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000249
250 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700251 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000252 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700253 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000254#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000255 uint32_t overlapCheck = 0;
256#endif
257 for (int i = 0; i < count; ++i) {
258 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
259 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700260 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000261 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000262 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700263 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000264 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000265#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000266 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
267 uint32_t mask = (1 << dwordCount)-1;
268 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000269 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000270 overlapCheck |= (mask << offsetShift);
271#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000272 }
egdaniel3658f382014-09-15 07:01:59 -0700273 this->invalidateOptState();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000274 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700275 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000276}
277
278////////////////////////////////////////////////////////////////////////////////
279
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000280void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000281 static const GrVertexAttrib kPositionAttrib =
282 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000283
bsalomon2ed5ef82014-07-07 08:44:05 -0700284 fVAPtr = &kPositionAttrib;
285 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700286 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000287
jvanverth@google.com054ae992013-04-01 20:06:51 +0000288 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700289 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000290 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700291 sizeof(fFixedFunctionVertexAttribIndices));
292 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel3658f382014-09-15 07:01:59 -0700293 this->invalidateOptState();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000294}
295
296////////////////////////////////////////////////////////////////////////////////
297
bsalomon62c447d2014-08-08 08:08:50 -0700298bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
299 if (caps.dualSourceBlendingSupport()) {
300 return true;
301 }
302 // we can correctly apply coverage if a) we have dual source blending
303 // or b) one of our blend optimizations applies
304 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
305 GrBlendCoeff srcCoeff;
306 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700307 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel21aed572014-08-26 12:24:06 -0700308 return GrRODrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700309 (this->willEffectReadDstColor() &&
310 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
311}
312
egdaniel21aed572014-08-26 12:24:06 -0700313//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000314
egdaniel3658f382014-09-15 07:01:59 -0700315GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700316 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700317 fDrawState = drawState;
318 fVAPtr = drawState->fVAPtr;
319 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700320 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700321 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000322}
323
egdaniel21aed572014-08-26 12:24:06 -0700324//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000325
egdaniel21aed572014-08-26 12:24:06 -0700326void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700327 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700328 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700329 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700330 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700331 } else {
332 SkASSERT(fDrawState->getGeometryProcessor()->getEffect()->getUniqueID() ==
333 fOriginalGPID);
334 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700335 }
joshualittbd769d02014-09-04 08:56:46 -0700336
egdaniel21aed572014-08-26 12:24:06 -0700337 int m = fDrawState->numColorStages() - fColorEffectCnt;
338 SkASSERT(m >= 0);
339 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000340
egdaniel21aed572014-08-26 12:24:06 -0700341 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
342 SkASSERT(n >= 0);
343 fDrawState->fCoverageStages.pop_back_n(n);
344 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700345 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700346 }
347 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000348 }
egdaniel21aed572014-08-26 12:24:06 -0700349 fDrawState = ds;
350 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700351 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700352 if (NULL != ds->getGeometryProcessor()) {
bsalomon52e9d632014-09-05 12:23:12 -0700353 fOriginalGPID = ds->getGeometryProcessor()->getEffect()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700354 }
egdaniel21aed572014-08-26 12:24:06 -0700355 fColorEffectCnt = ds->numColorStages();
356 fCoverageEffectCnt = ds->numCoverageStages();
357 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
358 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000359}
360
jvanverth@google.comcc782382013-01-28 20:39:48 +0000361////////////////////////////////////////////////////////////////////////////////
362
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000363void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700364 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000365 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700366 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000367 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000368 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000369 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000370
371 int i = 0;
joshualittbd769d02014-09-04 08:56:46 -0700372 if (fHasGeometryProcessor) {
373 SkASSERT(fDrawState->hasGeometryProcessor());
374 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
375 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000376 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700377 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000378 }
379 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700380 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000381 }
egdaniel3658f382014-09-15 07:01:59 -0700382 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000383 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000384 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000385}
386
387void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000388 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000389 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000390
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000391 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000392 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000393 return;
394 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000395 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000396
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000397 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700398 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000399
400 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000401 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700402 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000403}
404
bsalomon@google.com137f1342013-05-29 21:27:53 +0000405bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000406 this->restore();
407
bsalomon@google.com137f1342013-05-29 21:27:53 +0000408 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000409 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000410 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000411
bsalomon@google.com137f1342013-05-29 21:27:53 +0000412 if (drawState->getViewMatrix().isIdentity()) {
413 return true;
414 }
415
egdaniel3658f382014-09-15 07:01:59 -0700416 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000417 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000418 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700419 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000420 fDrawState = drawState;
joshualittbd769d02014-09-04 08:56:46 -0700421 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000422 fNumColorStages = 0;
423 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000424 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000425 return true;
426 } else {
427 SkMatrix inv;
428 if (!fViewMatrix.invert(&inv)) {
429 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000430 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700431 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000432 fDrawState = drawState;
433 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000434 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000435 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000436 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000437}
438
439void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
440 fSavedCoordChanges.reset(fDrawState->numTotalStages());
441 int i = 0;
442
joshualittbd769d02014-09-04 08:56:46 -0700443 fHasGeometryProcessor = false;
444 if (fDrawState->hasGeometryProcessor()) {
445 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
446 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
447 fHasGeometryProcessor = true;
448 }
449
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000450 fNumColorStages = fDrawState->numColorStages();
451 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700452 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700453 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000454 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000455
456 int numCoverageStages = fDrawState->numCoverageStages();
457 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700458 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700459 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000460 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000461}
egdaniel21aed572014-08-26 12:24:06 -0700462
egdaniel170f90b2014-09-16 12:54:40 -0700463////////////////////////////////////////////////////////////////////////////////
464
465void GrDrawState::invalidateOptState() const {
466 SkSafeSetNull(fCachedOptState);
467}
468
469////////////////////////////////////////////////////////////////////////////////
470
471GrDrawState::~GrDrawState() {
472 SkSafeUnref(fCachedOptState);
473 SkASSERT(0 == fBlockEffectRemovalCnt);
474}
475