blob: 0f2fcf070b373137138020af0e757ffcfdfef940 [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
egdaniel3658f382014-09-15 07:01:59 -070063 if (drawState.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -070064 fGeometryProcessor.initAndRef(drawState.fGeometryProcessor);
joshualitt4973d9d2014-11-08 09:24:25 -080065 } else if (!GrGpu::IsPathRenderingDrawType(drawType)) {
66 // Install default GP, this will be ignored if we are rendering with fragment shader only
67 // TODO(joshualitt) rendering code should do this
68 fGeometryProcessor.reset(GrDefaultGeoProcFactory::Create());
egdaniel3658f382014-09-15 07:01:59 -070069 } else {
70 fGeometryProcessor.reset(NULL);
71 }
72
egdaniel9cf45bf2014-10-08 06:49:10 -070073 // Copy Color Stages from DS to ODS
74 if (firstColorStageIdx < drawState.numColorStages()) {
egdanield9aa2182014-10-09 13:47:05 -070075 fFragmentStages.reset(&drawState.getColorStage(firstColorStageIdx),
76 drawState.numColorStages() - firstColorStageIdx);
egdaniel9cf45bf2014-10-08 06:49:10 -070077 } else {
egdanield9aa2182014-10-09 13:47:05 -070078 fFragmentStages.reset();
egdaniel9cf45bf2014-10-08 06:49:10 -070079 }
80
egdanield9aa2182014-10-09 13:47:05 -070081 fNumColorStages = fFragmentStages.count();
82
egdaniel9cf45bf2014-10-08 06:49:10 -070083 // Copy Coverage Stages from DS to ODS
egdanield9aa2182014-10-09 13:47:05 -070084 if (firstCoverageStageIdx < drawState.numCoverageStages()) {
85 fFragmentStages.push_back_n(drawState.numCoverageStages() - firstCoverageStageIdx,
86 &drawState.getCoverageStage(firstCoverageStageIdx));
egdaniel9cf45bf2014-10-08 06:49:10 -070087 }
joshualitt79f8fae2014-10-28 17:59:26 -070088
joshualitt4dd99882014-11-11 08:51:30 -080089 this->setOutputStateInfo(drawState, *gpu->caps(), &descInfo);
90
joshualitt79f8fae2014-10-28 17:59:26 -070091 // now create a key
92 gpu->buildProgramDesc(*this, descInfo, drawType, dstCopy, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -070093};
94
joshualitt79f8fae2014-10-28 17:59:26 -070095GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState,
96 GrGpu* gpu,
97 const GrDeviceCoordTexture* dstCopy,
egdanielb109ac22014-10-07 06:45:44 -070098 GrGpu::DrawType drawType) {
egdaniel69bb90c2014-11-11 07:32:45 -080099 GrBlendCoeff srcCoeff;
100 GrBlendCoeff dstCoeff;
101 BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false,
102 &srcCoeff,
103 &dstCoeff);
egdanielb109ac22014-10-07 06:45:44 -0700104
egdaniel69bb90c2014-11-11 07:32:45 -0800105 // If our blend coeffs are set to 0,1 we know we will not end up drawing unless we are
106 // stenciling. When path rendering the stencil settings are not always set on the draw state
107 // so we must check the draw type. In cases where we will skip drawing we simply return a
108 // null GrOptDrawState.
109 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff &&
110 !drawState.getStencil().doesWrite() && GrGpu::kStencilPath_DrawType != drawType) {
111 return NULL;
egdanielb109ac22014-10-07 06:45:44 -0700112 }
egdaniel69bb90c2014-11-11 07:32:45 -0800113
114 return SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff,
115 dstCoeff, gpu, dstCopy, drawType));
egdanielb109ac22014-10-07 06:45:44 -0700116}
117
egdaniel9cf45bf2014-10-08 06:49:10 -0700118void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
119 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800120 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700121 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700122 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
123 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700124
joshualitt4dd99882014-11-11 08:51:30 -0800125 // If we do have coverage determine whether it matters. Dual source blending is expensive so
126 // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source
127 // blending if we have any effective coverage stages OR the geometry processor doesn't emits
128 // solid coverage.
129 // TODO move the gp logic into the GP base class
130 if (!this->isCoverageDrawing() && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700131 if (caps.dualSourceBlendingSupport()) {
132 if (kZero_GrBlendCoeff == fDstBlend) {
133 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700134 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700135 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
136 } else if (kSA_GrBlendCoeff == fDstBlend) {
137 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700138 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700139 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
140 } else if (kSC_GrBlendCoeff == fDstBlend) {
141 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700142 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700143 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
144 }
joshualitt79f8fae2014-10-28 17:59:26 -0700145 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700146 kOne_GrBlendCoeff == fSrcBlend &&
147 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700148 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700149 }
150 }
egdanielc0648242014-09-22 13:17:02 -0700151}
152
egdaniel9cf45bf2014-10-08 06:49:10 -0700153void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds,
joshualitt79f8fae2014-10-28 17:59:26 -0700154 GrProgramDesc::DescInfo* descInfo,
egdaniel9cf45bf2014-10-08 06:49:10 -0700155 int* firstColorStageIdx,
156 int* firstCoverageStageIdx,
157 uint8_t* fixedFunctionVAToRemove) {
egdaniel170f90b2014-09-16 12:54:40 -0700158 switch (fBlendOptFlags) {
159 case kNone_BlendOpt:
160 case kSkipDraw_BlendOptFlag:
161 break;
162 case kCoverageAsAlpha_BlendOptFlag:
163 fFlagBits |= kCoverageDrawing_StateBit;
164 break;
165 case kEmitCoverage_BlendOptFlag:
166 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700167 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700168 *firstColorStageIdx = ds.numColorStages();
169 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel170f90b2014-09-16 12:54:40 -0700170 break;
171 case kEmitTransBlack_BlendOptFlag:
172 fColor = 0;
173 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700174 descInfo->fInputColorIsUsed = true;
175 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700176 *firstColorStageIdx = ds.numColorStages();
177 *firstCoverageStageIdx = ds.numCoverageStages();
178 *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
179 0x1 << kCoverage_GrVertexAttribBinding);
egdaniel170f90b2014-09-16 12:54:40 -0700180 break;
181 default:
182 SkFAIL("Unknown BlendOptFlag");
egdaniel170f90b2014-09-16 12:54:40 -0700183 }
184}
185
joshualitt79f8fae2014-10-28 17:59:26 -0700186void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag,
187 GrProgramDesc::DescInfo* descInfo) {
egdaniel3658f382014-09-15 07:01:59 -0700188 int numToRemove = 0;
189 uint8_t maskCheck = 0x1;
190 // Count the number of vertex attributes that we will actually remove
191 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
joshualitt79f8fae2014-10-28 17:59:26 -0700192 if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) {
egdaniel3658f382014-09-15 07:01:59 -0700193 ++numToRemove;
194 }
195 maskCheck <<= 1;
196 }
egdaniel170f90b2014-09-16 12:54:40 -0700197
egdaniel3658f382014-09-15 07:01:59 -0700198 fOptVA.reset(fVACount - numToRemove);
199
200 GrVertexAttrib* dst = fOptVA.get();
201 const GrVertexAttrib* src = fVAPtr;
202
203 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
204 const GrVertexAttrib& currAttrib = *src;
205 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
206 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
207 if (maskCheck & removeVAFlag) {
joshualitt79f8fae2014-10-28 17:59:26 -0700208 SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
209 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
egdaniel3658f382014-09-15 07:01:59 -0700210 continue;
211 }
joshualitt79f8fae2014-10-28 17:59:26 -0700212 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700213 }
214 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700215 ++newIdx;
216 ++dst;
217 }
218 fVACount -= numToRemove;
219 fVAPtr = fOptVA.get();
220}
221
joshualitt79f8fae2014-10-28 17:59:26 -0700222void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds,
223 GrProgramDesc::DescInfo* descInfo,
224 int* firstColorStageIdx,
egdaniel9cf45bf2014-10-08 06:49:10 -0700225 uint8_t* fixedFunctionVAToRemove) {
egdaniel3658f382014-09-15 07:01:59 -0700226 // Set up color and flags for ConstantColorComponent checks
egdaniel605dd0f2014-11-12 08:35:25 -0800227 GrColor color;
228 GrColorComponentFlags flags;
joshualitt79f8fae2014-10-28 17:59:26 -0700229 if (!descInfo->hasColorVertexAttribute()) {
egdaniel605dd0f2014-11-12 08:35:25 -0800230 color = ds.getColor();
231 flags = kRGBA_GrColorComponentFlags;
egdaniel3658f382014-09-15 07:01:59 -0700232 } else {
233 if (ds.vertexColorsAreOpaque()) {
egdaniel605dd0f2014-11-12 08:35:25 -0800234 color = 0xFF << GrColor_SHIFT_A;
235 flags = kA_GrColorComponentFlag;
egdaniel3658f382014-09-15 07:01:59 -0700236 } else {
egdaniel605dd0f2014-11-12 08:35:25 -0800237 flags = static_cast<GrColorComponentFlags>(0);
egdaniel1a8ecdf2014-10-03 06:24:12 -0700238 // not strictly necessary but we get false alarms from tools about uninit.
egdaniel605dd0f2014-11-12 08:35:25 -0800239 color = 0;
egdaniel3658f382014-09-15 07:01:59 -0700240 }
241 }
egdanielb6cbc382014-11-13 11:00:34 -0800242 GrProcOptInfo poi;
243 if (ds.numColorStages() > 0) {
244 poi.calcWithInitialValues(&ds.getColorStage(0), ds.numColorStages(), color, flags, false);
245 *firstColorStageIdx = poi.firstEffectiveStageIndex();
246 descInfo->fInputColorIsUsed = poi.inputColorIsUsed();
247 fColor = poi.inputColorToEffectiveStage();
248 if (poi.removeVertexAttrib()) {
egdaniel9cf45bf2014-10-08 06:49:10 -0700249 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel3658f382014-09-15 07:01:59 -0700250 }
251 }
egdaniel3658f382014-09-15 07:01:59 -0700252}
253
egdaniel9cf45bf2014-10-08 06:49:10 -0700254void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds,
joshualitt79f8fae2014-10-28 17:59:26 -0700255 GrProgramDesc::DescInfo* descInfo,
egdaniel9cf45bf2014-10-08 06:49:10 -0700256 int* firstCoverageStageIdx) {
egdaniel3658f382014-09-15 07:01:59 -0700257 // We do not try to optimize out constantColor coverage effects here. It is extremely rare
258 // to have a coverage effect that returns a constant value for all four channels. Thus we
259 // save having to make extra virtual calls by not checking for it.
260
261 // Don't do any optimizations on coverage stages. It should not be the case where we do not use
262 // input coverage in an effect
263#ifdef OptCoverageStages
egdaniel605dd0f2014-11-12 08:35:25 -0800264 GrInvariantOutput inout;
egdaniel3658f382014-09-15 07:01:59 -0700265 for (int i = 0; i < ds.numCoverageStages(); ++i) {
egdaniel9e4d6d12014-10-15 13:49:02 -0700266 const GrFragmentProcessor* fp = ds.getCoverageStage(i).getProcessor();
267 fp->computeInvariantOutput(&inout);
268 if (!inout.fWillUseInputColor) {
egdaniel9cf45bf2014-10-08 06:49:10 -0700269 *firstCoverageStageIdx = i;
joshualitt79f8fae2014-10-28 17:59:26 -0700270 descInfo->fInputCoverageIsUsed = false;
egdaniel3658f382014-09-15 07:01:59 -0700271 }
272 }
273#endif
egdaniel3658f382014-09-15 07:01:59 -0700274}
275
joshualittb0a8a372014-09-23 09:50:21 -0700276static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700277 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700278 *readsDst = true;
279 }
joshualitt47bb3822014-10-07 16:43:25 -0700280 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700281 *readsFragPosition = true;
282 }
283}
joshualittb0a8a372014-09-23 09:50:21 -0700284
egdaniel9cf45bf2014-10-08 06:49:10 -0700285void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt79f8fae2014-10-28 17:59:26 -0700286 int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700287 // We will need a local coord attrib if there is one currently set on the optState and we are
288 // actually generating some effect code
joshualitt79f8fae2014-10-28 17:59:26 -0700289 descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700290 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700291
joshualitt79f8fae2014-10-28 17:59:26 -0700292 descInfo->fReadsDst = false;
293 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700294
egdaniel9cf45bf2014-10-08 06:49:10 -0700295 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
296 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700297 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700298 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700299 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
300 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700301 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700302 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700303 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700304 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700305 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700306 }
307}
308
egdaniel89af44a2014-09-26 06:15:04 -0700309////////////////////////////////////////////////////////////////////////////////
310
egdaniel3658f382014-09-15 07:01:59 -0700311bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
312 return this->isEqual(that);
313}
314
egdaniel89af44a2014-09-26 06:15:04 -0700315bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700316 if (this->fDesc != that.fDesc) {
317 return false;
318 }
319 bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700320 if (!usingVertexColors && this->fColor != that.fColor) {
321 return false;
322 }
323
324 if (this->getRenderTarget() != that.getRenderTarget() ||
egdaniel89af44a2014-09-26 06:15:04 -0700325 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
326 this->fSrcBlend != that.fSrcBlend ||
327 this->fDstBlend != that.fDstBlend ||
328 this->fBlendConstant != that.fBlendConstant ||
329 this->fFlagBits != that.fFlagBits ||
330 this->fVACount != that.fVACount ||
331 this->fVAStride != that.fVAStride ||
332 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
333 this->fStencilSettings != that.fStencilSettings ||
joshualitt79f8fae2014-10-28 17:59:26 -0700334 this->fDrawFace != that.fDrawFace) {
egdaniel89af44a2014-09-26 06:15:04 -0700335 return false;
336 }
337
joshualitt79f8fae2014-10-28 17:59:26 -0700338 bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700339 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
340 return false;
341 }
342
egdaniel89af44a2014-09-26 06:15:04 -0700343 if (this->hasGeometryProcessor()) {
344 if (!that.hasGeometryProcessor()) {
345 return false;
joshualitta5305a12014-10-10 17:47:00 -0700346 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700347 return false;
348 }
349 } else if (that.hasGeometryProcessor()) {
350 return false;
351 }
352
joshualitt79f8fae2014-10-28 17:59:26 -0700353 bool explicitLocalCoords = this->fDesc.header().fLocalCoordAttributeIndex != -1;
egdanield9aa2182014-10-09 13:47:05 -0700354 for (int i = 0; i < this->numFragmentStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -0700355 if (!GrFragmentStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i),
356 explicitLocalCoords)) {
egdaniel89af44a2014-09-26 06:15:04 -0700357 return false;
358 }
359 }
egdaniel89af44a2014-09-26 06:15:04 -0700360 return true;
361}
362