blob: 24ba3a1879e934dd9f16b824f3fd82e6419bcaea [file] [log] [blame]
egdaniel3658f382014-09-15 07:01:59 -07001/*
2 * Copyright 2014 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 "GrOptDrawState.h"
9
joshualitt4973d9d2014-11-08 09:24:25 -080010#include "GrDefaultGeoProcFactory.h"
egdaniel3658f382014-09-15 07:01:59 -070011#include "GrDrawState.h"
egdanielc0648242014-09-22 13:17:02 -070012#include "GrDrawTargetCaps.h"
joshualitt4973d9d2014-11-08 09:24:25 -080013#include "GrGpu.h"
egdanielb6cbc382014-11-13 11:00:34 -080014#include "GrProcOptInfo.h"
egdaniel3658f382014-09-15 07:01:59 -070015
egdaniel170f90b2014-09-16 12:54:40 -070016GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
17 BlendOptFlags blendOptFlags,
18 GrBlendCoeff optSrcCoeff,
egdanielc0648242014-09-22 13:17:02 -070019 GrBlendCoeff optDstCoeff,
joshualitt79f8fae2014-10-28 17:59:26 -070020 GrGpu* gpu,
21 const GrDeviceCoordTexture* dstCopy,
22 GrGpu::DrawType drawType) {
bsalomonbcf0a522014-10-08 08:40:09 -070023 fRenderTarget.set(SkSafeRef(drawState.getRenderTarget()), kWrite_GrIOType);
egdaniel3658f382014-09-15 07:01:59 -070024 fColor = drawState.getColor();
25 fCoverage = drawState.getCoverage();
26 fViewMatrix = drawState.getViewMatrix();
27 fBlendConstant = drawState.getBlendConstant();
28 fFlagBits = drawState.getFlagBits();
29 fVAPtr = drawState.getVertexAttribs();
30 fVACount = drawState.getVertexAttribCount();
31 fVAStride = drawState.getVertexStride();
32 fStencilSettings = drawState.getStencil();
egdaniel89af44a2014-09-26 06:15:04 -070033 fDrawFace = (DrawFace)drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070034 fBlendOptFlags = blendOptFlags;
35 fSrcBlend = optSrcCoeff;
36 fDstBlend = optDstCoeff;
joshualitt79f8fae2014-10-28 17:59:26 -070037 GrProgramDesc::DescInfo descInfo;
egdaniel3658f382014-09-15 07:01:59 -070038
joshualitt79f8fae2014-10-28 17:59:26 -070039 memcpy(descInfo.fFixedFunctionVertexAttribIndices,
egdaniel89af44a2014-09-26 06:15:04 -070040 drawState.getFixedFunctionVertexAttribIndices(),
joshualitt79f8fae2014-10-28 17:59:26 -070041 sizeof(descInfo.fFixedFunctionVertexAttribIndices));
egdaniel3658f382014-09-15 07:01:59 -070042
joshualitt79f8fae2014-10-28 17:59:26 -070043 descInfo.fInputColorIsUsed = true;
44 descInfo.fInputCoverageIsUsed = true;
egdaniel3658f382014-09-15 07:01:59 -070045
egdaniel9cf45bf2014-10-08 06:49:10 -070046 int firstColorStageIdx = 0;
47 int firstCoverageStageIdx = 0;
egdaniel9cf45bf2014-10-08 06:49:10 -070048
49 uint8_t fixedFunctionVAToRemove = 0;
50
joshualitt79f8fae2014-10-28 17:59:26 -070051 this->computeEffectiveColorStages(drawState, &descInfo, &firstColorStageIdx,
52 &fixedFunctionVAToRemove);
53 this->computeEffectiveCoverageStages(drawState, &descInfo, &firstCoverageStageIdx);
54 this->adjustFromBlendOpts(drawState, &descInfo, &firstColorStageIdx, &firstCoverageStageIdx,
egdaniel9cf45bf2014-10-08 06:49:10 -070055 &fixedFunctionVAToRemove);
56 // Should not be setting any more FFVA to be removed at this point
egdanielc0651c12014-10-21 07:47:10 -070057 if (0 != fixedFunctionVAToRemove) {
joshualitt79f8fae2014-10-28 17:59:26 -070058 this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo);
egdanielc0651c12014-10-21 07:47:10 -070059 }
joshualitt79f8fae2014-10-28 17:59:26 -070060 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo);
egdaniel9cf45bf2014-10-08 06:49:10 -070061
62 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -080063 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
64 GrGpu::kStencilPath_DrawType ||
65 drawState.hasGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -070066 if (drawState.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -070067 fGeometryProcessor.initAndRef(drawState.fGeometryProcessor);
egdaniel3658f382014-09-15 07:01:59 -070068 } else {
69 fGeometryProcessor.reset(NULL);
70 }
71
egdaniel9cf45bf2014-10-08 06:49:10 -070072 // Copy Color Stages from DS to ODS
73 if (firstColorStageIdx < drawState.numColorStages()) {
egdanield9aa2182014-10-09 13:47:05 -070074 fFragmentStages.reset(&drawState.getColorStage(firstColorStageIdx),
75 drawState.numColorStages() - firstColorStageIdx);
egdaniel9cf45bf2014-10-08 06:49:10 -070076 } else {
egdanield9aa2182014-10-09 13:47:05 -070077 fFragmentStages.reset();
egdaniel9cf45bf2014-10-08 06:49:10 -070078 }
79
egdanield9aa2182014-10-09 13:47:05 -070080 fNumColorStages = fFragmentStages.count();
81
egdaniel9cf45bf2014-10-08 06:49:10 -070082 // Copy Coverage Stages from DS to ODS
egdanield9aa2182014-10-09 13:47:05 -070083 if (firstCoverageStageIdx < drawState.numCoverageStages()) {
84 fFragmentStages.push_back_n(drawState.numCoverageStages() - firstCoverageStageIdx,
85 &drawState.getCoverageStage(firstCoverageStageIdx));
egdaniel9cf45bf2014-10-08 06:49:10 -070086 }
joshualitt79f8fae2014-10-28 17:59:26 -070087
joshualitt4dd99882014-11-11 08:51:30 -080088 this->setOutputStateInfo(drawState, *gpu->caps(), &descInfo);
89
joshualitt79f8fae2014-10-28 17:59:26 -070090 // now create a key
91 gpu->buildProgramDesc(*this, descInfo, drawType, dstCopy, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -070092};
93
joshualitt79f8fae2014-10-28 17:59:26 -070094GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState,
95 GrGpu* gpu,
96 const GrDeviceCoordTexture* dstCopy,
egdanielb109ac22014-10-07 06:45:44 -070097 GrGpu::DrawType drawType) {
egdaniel69bb90c2014-11-11 07:32:45 -080098 GrBlendCoeff srcCoeff;
99 GrBlendCoeff dstCoeff;
100 BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false,
101 &srcCoeff,
102 &dstCoeff);
egdanielb109ac22014-10-07 06:45:44 -0700103
egdaniel69bb90c2014-11-11 07:32:45 -0800104 // If our blend coeffs are set to 0,1 we know we will not end up drawing unless we are
105 // stenciling. When path rendering the stencil settings are not always set on the draw state
106 // so we must check the draw type. In cases where we will skip drawing we simply return a
107 // null GrOptDrawState.
108 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff &&
109 !drawState.getStencil().doesWrite() && GrGpu::kStencilPath_DrawType != drawType) {
110 return NULL;
egdanielb109ac22014-10-07 06:45:44 -0700111 }
egdaniel69bb90c2014-11-11 07:32:45 -0800112
113 return SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff,
114 dstCoeff, gpu, dstCopy, drawType));
egdanielb109ac22014-10-07 06:45:44 -0700115}
116
egdaniel9cf45bf2014-10-08 06:49:10 -0700117void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
118 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800119 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700120 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700121 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
122 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700123
joshualitt4dd99882014-11-11 08:51:30 -0800124 // If we do have coverage determine whether it matters. Dual source blending is expensive so
125 // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source
126 // blending if we have any effective coverage stages OR the geometry processor doesn't emits
127 // solid coverage.
128 // TODO move the gp logic into the GP base class
129 if (!this->isCoverageDrawing() && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700130 if (caps.dualSourceBlendingSupport()) {
131 if (kZero_GrBlendCoeff == fDstBlend) {
132 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700133 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700134 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
135 } else if (kSA_GrBlendCoeff == fDstBlend) {
136 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700137 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700138 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
139 } else if (kSC_GrBlendCoeff == fDstBlend) {
140 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700141 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700142 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
143 }
joshualitt79f8fae2014-10-28 17:59:26 -0700144 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700145 kOne_GrBlendCoeff == fSrcBlend &&
146 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700147 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700148 }
149 }
egdanielc0648242014-09-22 13:17:02 -0700150}
151
egdaniel9cf45bf2014-10-08 06:49:10 -0700152void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds,
joshualitt79f8fae2014-10-28 17:59:26 -0700153 GrProgramDesc::DescInfo* descInfo,
egdaniel9cf45bf2014-10-08 06:49:10 -0700154 int* firstColorStageIdx,
155 int* firstCoverageStageIdx,
156 uint8_t* fixedFunctionVAToRemove) {
egdaniel170f90b2014-09-16 12:54:40 -0700157 switch (fBlendOptFlags) {
158 case kNone_BlendOpt:
159 case kSkipDraw_BlendOptFlag:
160 break;
161 case kCoverageAsAlpha_BlendOptFlag:
162 fFlagBits |= kCoverageDrawing_StateBit;
163 break;
164 case kEmitCoverage_BlendOptFlag:
165 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700166 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700167 *firstColorStageIdx = ds.numColorStages();
168 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel170f90b2014-09-16 12:54:40 -0700169 break;
170 case kEmitTransBlack_BlendOptFlag:
171 fColor = 0;
172 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700173 descInfo->fInputColorIsUsed = true;
174 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700175 *firstColorStageIdx = ds.numColorStages();
176 *firstCoverageStageIdx = ds.numCoverageStages();
177 *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
178 0x1 << kCoverage_GrVertexAttribBinding);
egdaniel170f90b2014-09-16 12:54:40 -0700179 break;
180 default:
181 SkFAIL("Unknown BlendOptFlag");
egdaniel170f90b2014-09-16 12:54:40 -0700182 }
183}
184
joshualitt79f8fae2014-10-28 17:59:26 -0700185void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag,
186 GrProgramDesc::DescInfo* descInfo) {
egdaniel3658f382014-09-15 07:01:59 -0700187 int numToRemove = 0;
188 uint8_t maskCheck = 0x1;
189 // Count the number of vertex attributes that we will actually remove
190 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
joshualitt79f8fae2014-10-28 17:59:26 -0700191 if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) {
egdaniel3658f382014-09-15 07:01:59 -0700192 ++numToRemove;
193 }
194 maskCheck <<= 1;
195 }
egdaniel170f90b2014-09-16 12:54:40 -0700196
egdaniel3658f382014-09-15 07:01:59 -0700197 fOptVA.reset(fVACount - numToRemove);
198
199 GrVertexAttrib* dst = fOptVA.get();
200 const GrVertexAttrib* src = fVAPtr;
201
202 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
203 const GrVertexAttrib& currAttrib = *src;
204 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
205 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
206 if (maskCheck & removeVAFlag) {
joshualitt79f8fae2014-10-28 17:59:26 -0700207 SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
208 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
egdaniel3658f382014-09-15 07:01:59 -0700209 continue;
210 }
joshualitt79f8fae2014-10-28 17:59:26 -0700211 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700212 }
213 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700214 ++newIdx;
215 ++dst;
216 }
217 fVACount -= numToRemove;
218 fVAPtr = fOptVA.get();
219}
220
joshualitt79f8fae2014-10-28 17:59:26 -0700221void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds,
222 GrProgramDesc::DescInfo* descInfo,
223 int* firstColorStageIdx,
egdaniel9cf45bf2014-10-08 06:49:10 -0700224 uint8_t* fixedFunctionVAToRemove) {
egdaniel3658f382014-09-15 07:01:59 -0700225 // Set up color and flags for ConstantColorComponent checks
egdaniel605dd0f2014-11-12 08:35:25 -0800226 GrColor color;
227 GrColorComponentFlags flags;
joshualitt79f8fae2014-10-28 17:59:26 -0700228 if (!descInfo->hasColorVertexAttribute()) {
egdaniel605dd0f2014-11-12 08:35:25 -0800229 color = ds.getColor();
230 flags = kRGBA_GrColorComponentFlags;
egdaniel3658f382014-09-15 07:01:59 -0700231 } else {
232 if (ds.vertexColorsAreOpaque()) {
egdaniel605dd0f2014-11-12 08:35:25 -0800233 color = 0xFF << GrColor_SHIFT_A;
234 flags = kA_GrColorComponentFlag;
egdaniel3658f382014-09-15 07:01:59 -0700235 } else {
egdaniel605dd0f2014-11-12 08:35:25 -0800236 flags = static_cast<GrColorComponentFlags>(0);
egdaniel1a8ecdf2014-10-03 06:24:12 -0700237 // not strictly necessary but we get false alarms from tools about uninit.
egdaniel605dd0f2014-11-12 08:35:25 -0800238 color = 0;
egdaniel3658f382014-09-15 07:01:59 -0700239 }
240 }
egdanielb6cbc382014-11-13 11:00:34 -0800241 GrProcOptInfo poi;
242 if (ds.numColorStages() > 0) {
243 poi.calcWithInitialValues(&ds.getColorStage(0), ds.numColorStages(), color, flags, false);
244 *firstColorStageIdx = poi.firstEffectiveStageIndex();
245 descInfo->fInputColorIsUsed = poi.inputColorIsUsed();
246 fColor = poi.inputColorToEffectiveStage();
247 if (poi.removeVertexAttrib()) {
egdaniel9cf45bf2014-10-08 06:49:10 -0700248 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel3658f382014-09-15 07:01:59 -0700249 }
250 }
egdaniel3658f382014-09-15 07:01:59 -0700251}
252
egdaniel9cf45bf2014-10-08 06:49:10 -0700253void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds,
joshualitt79f8fae2014-10-28 17:59:26 -0700254 GrProgramDesc::DescInfo* descInfo,
egdaniel9cf45bf2014-10-08 06:49:10 -0700255 int* firstCoverageStageIdx) {
egdaniel3658f382014-09-15 07:01:59 -0700256 // We do not try to optimize out constantColor coverage effects here. It is extremely rare
257 // to have a coverage effect that returns a constant value for all four channels. Thus we
258 // save having to make extra virtual calls by not checking for it.
259
260 // Don't do any optimizations on coverage stages. It should not be the case where we do not use
261 // input coverage in an effect
262#ifdef OptCoverageStages
egdaniel605dd0f2014-11-12 08:35:25 -0800263 GrInvariantOutput inout;
egdaniel3658f382014-09-15 07:01:59 -0700264 for (int i = 0; i < ds.numCoverageStages(); ++i) {
egdaniel9e4d6d12014-10-15 13:49:02 -0700265 const GrFragmentProcessor* fp = ds.getCoverageStage(i).getProcessor();
266 fp->computeInvariantOutput(&inout);
267 if (!inout.fWillUseInputColor) {
egdaniel9cf45bf2014-10-08 06:49:10 -0700268 *firstCoverageStageIdx = i;
joshualitt79f8fae2014-10-28 17:59:26 -0700269 descInfo->fInputCoverageIsUsed = false;
egdaniel3658f382014-09-15 07:01:59 -0700270 }
271 }
272#endif
egdaniel3658f382014-09-15 07:01:59 -0700273}
274
joshualittb0a8a372014-09-23 09:50:21 -0700275static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700276 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700277 *readsDst = true;
278 }
joshualitt47bb3822014-10-07 16:43:25 -0700279 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700280 *readsFragPosition = true;
281 }
282}
joshualittb0a8a372014-09-23 09:50:21 -0700283
egdaniel9cf45bf2014-10-08 06:49:10 -0700284void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt79f8fae2014-10-28 17:59:26 -0700285 int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700286 // We will need a local coord attrib if there is one currently set on the optState and we are
287 // actually generating some effect code
joshualitt79f8fae2014-10-28 17:59:26 -0700288 descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700289 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700290
joshualitt79f8fae2014-10-28 17:59:26 -0700291 descInfo->fReadsDst = false;
292 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700293
egdaniel9cf45bf2014-10-08 06:49:10 -0700294 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
295 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700296 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700297 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700298 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
299 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700300 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700301 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700302 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700303 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700304 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700305 }
306}
307
egdaniel89af44a2014-09-26 06:15:04 -0700308////////////////////////////////////////////////////////////////////////////////
309
egdaniel3658f382014-09-15 07:01:59 -0700310bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
311 return this->isEqual(that);
312}
313
egdaniel89af44a2014-09-26 06:15:04 -0700314bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700315 if (this->fDesc != that.fDesc) {
316 return false;
317 }
318 bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700319 if (!usingVertexColors && this->fColor != that.fColor) {
320 return false;
321 }
322
323 if (this->getRenderTarget() != that.getRenderTarget() ||
egdaniel89af44a2014-09-26 06:15:04 -0700324 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
325 this->fSrcBlend != that.fSrcBlend ||
326 this->fDstBlend != that.fDstBlend ||
327 this->fBlendConstant != that.fBlendConstant ||
328 this->fFlagBits != that.fFlagBits ||
329 this->fVACount != that.fVACount ||
330 this->fVAStride != that.fVAStride ||
331 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
332 this->fStencilSettings != that.fStencilSettings ||
joshualitt79f8fae2014-10-28 17:59:26 -0700333 this->fDrawFace != that.fDrawFace) {
egdaniel89af44a2014-09-26 06:15:04 -0700334 return false;
335 }
336
joshualitt79f8fae2014-10-28 17:59:26 -0700337 bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700338 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
339 return false;
340 }
341
egdaniel89af44a2014-09-26 06:15:04 -0700342 if (this->hasGeometryProcessor()) {
343 if (!that.hasGeometryProcessor()) {
344 return false;
joshualitta5305a12014-10-10 17:47:00 -0700345 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700346 return false;
347 }
348 } else if (that.hasGeometryProcessor()) {
349 return false;
350 }
351
joshualitt79f8fae2014-10-28 17:59:26 -0700352 bool explicitLocalCoords = this->fDesc.header().fLocalCoordAttributeIndex != -1;
egdanield9aa2182014-10-09 13:47:05 -0700353 for (int i = 0; i < this->numFragmentStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -0700354 if (!GrFragmentStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i),
355 explicitLocalCoords)) {
egdaniel89af44a2014-09-26 06:15:04 -0700356 return false;
357 }
358 }
egdaniel89af44a2014-09-26 06:15:04 -0700359 return true;
360}
361