blob: a494b171de3a77e652191d0abf153ff548cd5586 [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,
joshualitt79f8fae2014-10-28 17:59:26 -070017 GrGpu* gpu,
joshualitt54e0c122014-11-19 09:38:51 -080018 const ScissorState& scissorState,
joshualitt79f8fae2014-10-28 17:59:26 -070019 const GrDeviceCoordTexture* dstCopy,
bsalomonb03c4a32014-11-20 09:56:11 -080020 GrGpu::DrawType drawType) {
21
22 GrBlendCoeff optSrcCoeff;
23 GrBlendCoeff optDstCoeff;
24 GrDrawState::BlendOpt blendOpt = drawState.getBlendOpt(false, &optSrcCoeff, &optDstCoeff);
25
26 // When path rendering the stencil settings are not always set on the draw state
27 // so we must check the draw type. In cases where we will skip drawing we simply return a
28 // null GrOptDrawState.
29 if (GrDrawState::kSkipDraw_BlendOpt == blendOpt && GrGpu::kStencilPath_DrawType != drawType) {
30 // Set the fields that don't default init and return. The lack of a render target will
31 // indicate that this can be skipped.
32 fFlags = 0;
33 fVAPtr = NULL;
34 fVACount = 0;
35 fVAStride = 0;
36 fDrawFace = GrDrawState::kInvalid_DrawFace;
37 fSrcBlend = kZero_GrBlendCoeff;
38 fDstBlend = kZero_GrBlendCoeff;
39 fBlendConstant = 0x0;
40 fViewMatrix.reset();
41 return;
42 }
43
44 fRenderTarget.reset(drawState.fRenderTarget.get());
45 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080046 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070047 fViewMatrix = drawState.getViewMatrix();
48 fBlendConstant = drawState.getBlendConstant();
egdaniel3658f382014-09-15 07:01:59 -070049 fVAPtr = drawState.getVertexAttribs();
50 fVACount = drawState.getVertexAttribCount();
51 fVAStride = drawState.getVertexStride();
52 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080053 fDrawFace = drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070054 fSrcBlend = optSrcCoeff;
55 fDstBlend = optDstCoeff;
joshualitt9176e2c2014-11-20 07:28:52 -080056
57 // TODO move this out of optDrawState
58 if (dstCopy) {
59 fDstCopy = *dstCopy;
60 }
61
joshualitt79f8fae2014-10-28 17:59:26 -070062 GrProgramDesc::DescInfo descInfo;
egdaniel3658f382014-09-15 07:01:59 -070063
bsalomon04ddf892014-11-19 12:36:22 -080064 fFlags = 0;
65 if (drawState.isHWAntialias()) {
66 fFlags |= kHWAA_Flag;
67 }
68 if (drawState.isColorWriteDisabled()) {
69 fFlags |= kDisableColorWrite_Flag;
70 }
71 if (drawState.isDither()) {
72 fFlags |= kDither_Flag;
73 }
74
joshualitt79f8fae2014-10-28 17:59:26 -070075 memcpy(descInfo.fFixedFunctionVertexAttribIndices,
egdaniel89af44a2014-09-26 06:15:04 -070076 drawState.getFixedFunctionVertexAttribIndices(),
joshualitt79f8fae2014-10-28 17:59:26 -070077 sizeof(descInfo.fFixedFunctionVertexAttribIndices));
egdaniel3658f382014-09-15 07:01:59 -070078
egdaniel9cf45bf2014-10-08 06:49:10 -070079 uint8_t fixedFunctionVAToRemove = 0;
80
egdaniel912b3d22014-11-17 07:45:53 -080081 const GrProcOptInfo& colorPOI = drawState.colorProcInfo();
82 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
83 descInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
84 fColor = colorPOI.inputColorToEffectiveStage();
85 if (colorPOI.removeVertexAttrib()) {
86 fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
87 }
88
89 // TODO: Once we can handle single or four channel input into coverage stages then we can use
90 // drawState's coverageProcInfo (like color above) to set this initial information.
91 int firstCoverageStageIdx = 0;
92 descInfo.fInputCoverageIsUsed = true;
93 fCoverage = drawState.getCoverage();
94
bsalomon04ddf892014-11-19 12:36:22 -080095 this->adjustProgramForBlendOpt(drawState, blendOpt, &descInfo, &firstColorStageIdx,
96 &firstCoverageStageIdx, &fixedFunctionVAToRemove);
egdaniel9cf45bf2014-10-08 06:49:10 -070097 // Should not be setting any more FFVA to be removed at this point
egdanielc0651c12014-10-21 07:47:10 -070098 if (0 != fixedFunctionVAToRemove) {
joshualitt79f8fae2014-10-28 17:59:26 -070099 this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo);
egdanielc0651c12014-10-21 07:47:10 -0700100 }
joshualitt79f8fae2014-10-28 17:59:26 -0700101 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo);
egdaniel9cf45bf2014-10-08 06:49:10 -0700102
103 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -0800104 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
105 GrGpu::kStencilPath_DrawType ||
106 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -0800107 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -0700108
bsalomonae59b772014-11-19 08:23:49 -0800109 // Copy Stages from DS to ODS
110 bool explicitLocalCoords = descInfo.hasLocalCoordAttribute();
egdaniel9cf45bf2014-10-08 06:49:10 -0700111
bsalomonae59b772014-11-19 08:23:49 -0800112 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
113 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
114 GrPendingFragmentStage,
115 (drawState.fColorStages[i], explicitLocalCoords));
116 }
egdanield9aa2182014-10-09 13:47:05 -0700117 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800118 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
119 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
120 GrPendingFragmentStage,
121 (drawState.fCoverageStages[i], explicitLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700122 }
joshualitt79f8fae2014-10-28 17:59:26 -0700123
bsalomon04ddf892014-11-19 12:36:22 -0800124 this->setOutputStateInfo(drawState, blendOpt, *gpu->caps(), &descInfo);
joshualitt4dd99882014-11-11 08:51:30 -0800125
joshualitt79f8fae2014-10-28 17:59:26 -0700126 // now create a key
joshualitt9176e2c2014-11-20 07:28:52 -0800127 gpu->buildProgramDesc(*this, descInfo, drawType, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -0700128};
129
egdaniel9cf45bf2014-10-08 06:49:10 -0700130void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
bsalomon04ddf892014-11-19 12:36:22 -0800131 GrDrawState::BlendOpt blendOpt,
egdaniel9cf45bf2014-10-08 06:49:10 -0700132 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800133 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700134 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700135 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
136 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700137
bsalomon04ddf892014-11-19 12:36:22 -0800138 // Determine whether we should use dual source blending or shader code to keep coverage
139 // separate from color.
140 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blendOpt ||
141 GrDrawState::kEmitCoverage_BlendOpt == blendOpt);
142 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700143 if (caps.dualSourceBlendingSupport()) {
144 if (kZero_GrBlendCoeff == fDstBlend) {
145 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700146 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700147 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
148 } else if (kSA_GrBlendCoeff == fDstBlend) {
149 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700150 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700151 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
152 } else if (kSC_GrBlendCoeff == fDstBlend) {
153 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700154 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700155 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
156 }
joshualitt79f8fae2014-10-28 17:59:26 -0700157 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700158 kOne_GrBlendCoeff == fSrcBlend &&
159 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700160 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700161 }
162 }
egdanielc0648242014-09-22 13:17:02 -0700163}
164
bsalomon04ddf892014-11-19 12:36:22 -0800165void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds,
166 GrDrawState::BlendOpt blendOpt,
167 GrProgramDesc::DescInfo* descInfo,
168 int* firstColorStageIdx,
169 int* firstCoverageStageIdx,
170 uint8_t* fixedFunctionVAToRemove) {
171 switch (blendOpt) {
172 case GrDrawState::kNone_BlendOpt:
173 case GrDrawState::kSkipDraw_BlendOpt:
174 case GrDrawState::kCoverageAsAlpha_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700175 break;
bsalomon04ddf892014-11-19 12:36:22 -0800176 case GrDrawState::kEmitCoverage_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700177 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700178 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700179 *firstColorStageIdx = ds.numColorStages();
180 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel170f90b2014-09-16 12:54:40 -0700181 break;
bsalomon04ddf892014-11-19 12:36:22 -0800182 case GrDrawState::kEmitTransBlack_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700183 fColor = 0;
184 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700185 descInfo->fInputColorIsUsed = true;
186 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700187 *firstColorStageIdx = ds.numColorStages();
188 *firstCoverageStageIdx = ds.numCoverageStages();
189 *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
190 0x1 << kCoverage_GrVertexAttribBinding);
egdaniel170f90b2014-09-16 12:54:40 -0700191 break;
egdaniel170f90b2014-09-16 12:54:40 -0700192 }
193}
194
joshualitt79f8fae2014-10-28 17:59:26 -0700195void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag,
196 GrProgramDesc::DescInfo* descInfo) {
egdaniel3658f382014-09-15 07:01:59 -0700197 int numToRemove = 0;
198 uint8_t maskCheck = 0x1;
199 // Count the number of vertex attributes that we will actually remove
200 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
joshualitt79f8fae2014-10-28 17:59:26 -0700201 if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) {
egdaniel3658f382014-09-15 07:01:59 -0700202 ++numToRemove;
203 }
204 maskCheck <<= 1;
205 }
egdaniel170f90b2014-09-16 12:54:40 -0700206
egdaniel3658f382014-09-15 07:01:59 -0700207 fOptVA.reset(fVACount - numToRemove);
208
209 GrVertexAttrib* dst = fOptVA.get();
210 const GrVertexAttrib* src = fVAPtr;
211
212 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
213 const GrVertexAttrib& currAttrib = *src;
214 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
215 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
216 if (maskCheck & removeVAFlag) {
joshualitt79f8fae2014-10-28 17:59:26 -0700217 SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
218 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
egdaniel3658f382014-09-15 07:01:59 -0700219 continue;
220 }
joshualitt79f8fae2014-10-28 17:59:26 -0700221 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700222 }
223 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700224 ++newIdx;
225 ++dst;
226 }
227 fVACount -= numToRemove;
228 fVAPtr = fOptVA.get();
229}
230
joshualittb0a8a372014-09-23 09:50:21 -0700231static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700232 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700233 *readsDst = true;
234 }
joshualitt47bb3822014-10-07 16:43:25 -0700235 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700236 *readsFragPosition = true;
237 }
238}
joshualittb0a8a372014-09-23 09:50:21 -0700239
egdaniel9cf45bf2014-10-08 06:49:10 -0700240void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt79f8fae2014-10-28 17:59:26 -0700241 int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700242 // We will need a local coord attrib if there is one currently set on the optState and we are
243 // actually generating some effect code
joshualitt79f8fae2014-10-28 17:59:26 -0700244 descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700245 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700246
joshualitt79f8fae2014-10-28 17:59:26 -0700247 descInfo->fReadsDst = false;
248 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700249
egdaniel9cf45bf2014-10-08 06:49:10 -0700250 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
251 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700252 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700253 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700254 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
255 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700256 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700257 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700258 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700259 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700260 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700261 }
262}
263
egdaniel89af44a2014-09-26 06:15:04 -0700264////////////////////////////////////////////////////////////////////////////////
265
egdaniel3658f382014-09-15 07:01:59 -0700266bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700267 if (this->fDesc != that.fDesc) {
268 return false;
269 }
270 bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700271 if (!usingVertexColors && this->fColor != that.fColor) {
272 return false;
273 }
274
275 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualitt54e0c122014-11-19 09:38:51 -0800276 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700277 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
278 this->fSrcBlend != that.fSrcBlend ||
279 this->fDstBlend != that.fDstBlend ||
280 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800281 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700282 this->fVACount != that.fVACount ||
283 this->fVAStride != that.fVAStride ||
284 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
285 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800286 this->fDrawFace != that.fDrawFace ||
287 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700288 return false;
289 }
290
joshualitt79f8fae2014-10-28 17:59:26 -0700291 bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700292 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
293 return false;
294 }
295
egdaniel89af44a2014-09-26 06:15:04 -0700296 if (this->hasGeometryProcessor()) {
297 if (!that.hasGeometryProcessor()) {
298 return false;
joshualitta5305a12014-10-10 17:47:00 -0700299 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700300 return false;
301 }
302 } else if (that.hasGeometryProcessor()) {
303 return false;
304 }
305
bsalomonae59b772014-11-19 08:23:49 -0800306 // The program desc comparison should have already assured that the stage counts match.
307 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700308 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800309
310 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700311 return false;
312 }
313 }
egdaniel89af44a2014-09-26 06:15:04 -0700314 return true;
315}
316