blob: 4b20fa901c79628bd4456226af61125fec7b5fbe [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,
bsalomonae59b772014-11-19 08:23:49 -080022 GrGpu::DrawType drawType)
23: fRenderTarget(drawState.fRenderTarget.get()) {
egdaniel3658f382014-09-15 07:01:59 -070024 fViewMatrix = drawState.getViewMatrix();
25 fBlendConstant = drawState.getBlendConstant();
26 fFlagBits = drawState.getFlagBits();
27 fVAPtr = drawState.getVertexAttribs();
28 fVACount = drawState.getVertexAttribCount();
29 fVAStride = drawState.getVertexStride();
30 fStencilSettings = drawState.getStencil();
egdaniel89af44a2014-09-26 06:15:04 -070031 fDrawFace = (DrawFace)drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070032 fBlendOptFlags = blendOptFlags;
33 fSrcBlend = optSrcCoeff;
34 fDstBlend = optDstCoeff;
joshualitt79f8fae2014-10-28 17:59:26 -070035 GrProgramDesc::DescInfo descInfo;
egdaniel3658f382014-09-15 07:01:59 -070036
joshualitt79f8fae2014-10-28 17:59:26 -070037 memcpy(descInfo.fFixedFunctionVertexAttribIndices,
egdaniel89af44a2014-09-26 06:15:04 -070038 drawState.getFixedFunctionVertexAttribIndices(),
joshualitt79f8fae2014-10-28 17:59:26 -070039 sizeof(descInfo.fFixedFunctionVertexAttribIndices));
egdaniel3658f382014-09-15 07:01:59 -070040
egdaniel9cf45bf2014-10-08 06:49:10 -070041 uint8_t fixedFunctionVAToRemove = 0;
42
egdaniel912b3d22014-11-17 07:45:53 -080043 const GrProcOptInfo& colorPOI = drawState.colorProcInfo();
44 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
45 descInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
46 fColor = colorPOI.inputColorToEffectiveStage();
47 if (colorPOI.removeVertexAttrib()) {
48 fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
49 }
50
51 // TODO: Once we can handle single or four channel input into coverage stages then we can use
52 // drawState's coverageProcInfo (like color above) to set this initial information.
53 int firstCoverageStageIdx = 0;
54 descInfo.fInputCoverageIsUsed = true;
55 fCoverage = drawState.getCoverage();
56
joshualitt79f8fae2014-10-28 17:59:26 -070057 this->adjustFromBlendOpts(drawState, &descInfo, &firstColorStageIdx, &firstCoverageStageIdx,
egdaniel9cf45bf2014-10-08 06:49:10 -070058 &fixedFunctionVAToRemove);
59 // Should not be setting any more FFVA to be removed at this point
egdanielc0651c12014-10-21 07:47:10 -070060 if (0 != fixedFunctionVAToRemove) {
joshualitt79f8fae2014-10-28 17:59:26 -070061 this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo);
egdanielc0651c12014-10-21 07:47:10 -070062 }
joshualitt79f8fae2014-10-28 17:59:26 -070063 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo);
egdaniel9cf45bf2014-10-08 06:49:10 -070064
65 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -080066 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
67 GrGpu::kStencilPath_DrawType ||
68 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -080069 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -070070
bsalomonae59b772014-11-19 08:23:49 -080071 // Copy Stages from DS to ODS
72 bool explicitLocalCoords = descInfo.hasLocalCoordAttribute();
egdaniel9cf45bf2014-10-08 06:49:10 -070073
bsalomonae59b772014-11-19 08:23:49 -080074 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
75 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
76 GrPendingFragmentStage,
77 (drawState.fColorStages[i], explicitLocalCoords));
78 }
egdanield9aa2182014-10-09 13:47:05 -070079 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -080080 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
81 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
82 GrPendingFragmentStage,
83 (drawState.fCoverageStages[i], explicitLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -070084 }
joshualitt79f8fae2014-10-28 17:59:26 -070085
joshualitt4dd99882014-11-11 08:51:30 -080086 this->setOutputStateInfo(drawState, *gpu->caps(), &descInfo);
87
joshualitt79f8fae2014-10-28 17:59:26 -070088 // now create a key
89 gpu->buildProgramDesc(*this, descInfo, drawType, dstCopy, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -070090};
91
joshualitt79f8fae2014-10-28 17:59:26 -070092GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState,
93 GrGpu* gpu,
94 const GrDeviceCoordTexture* dstCopy,
egdanielb109ac22014-10-07 06:45:44 -070095 GrGpu::DrawType drawType) {
egdaniel69bb90c2014-11-11 07:32:45 -080096 GrBlendCoeff srcCoeff;
97 GrBlendCoeff dstCoeff;
98 BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false,
99 &srcCoeff,
100 &dstCoeff);
egdanielb109ac22014-10-07 06:45:44 -0700101
egdaniel69bb90c2014-11-11 07:32:45 -0800102 // If our blend coeffs are set to 0,1 we know we will not end up drawing unless we are
103 // stenciling. When path rendering the stencil settings are not always set on the draw state
104 // so we must check the draw type. In cases where we will skip drawing we simply return a
105 // null GrOptDrawState.
106 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff &&
107 !drawState.getStencil().doesWrite() && GrGpu::kStencilPath_DrawType != drawType) {
108 return NULL;
egdanielb109ac22014-10-07 06:45:44 -0700109 }
egdaniel69bb90c2014-11-11 07:32:45 -0800110
111 return SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff,
112 dstCoeff, gpu, dstCopy, drawType));
egdanielb109ac22014-10-07 06:45:44 -0700113}
114
egdaniel9cf45bf2014-10-08 06:49:10 -0700115void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
116 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800117 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700118 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700119 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
120 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700121
joshualitt4dd99882014-11-11 08:51:30 -0800122 // If we do have coverage determine whether it matters. Dual source blending is expensive so
123 // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source
124 // blending if we have any effective coverage stages OR the geometry processor doesn't emits
125 // solid coverage.
126 // TODO move the gp logic into the GP base class
127 if (!this->isCoverageDrawing() && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700128 if (caps.dualSourceBlendingSupport()) {
129 if (kZero_GrBlendCoeff == fDstBlend) {
130 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700131 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700132 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
133 } else if (kSA_GrBlendCoeff == fDstBlend) {
134 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700135 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700136 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
137 } else if (kSC_GrBlendCoeff == fDstBlend) {
138 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700139 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700140 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
141 }
joshualitt79f8fae2014-10-28 17:59:26 -0700142 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700143 kOne_GrBlendCoeff == fSrcBlend &&
144 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700145 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700146 }
147 }
egdanielc0648242014-09-22 13:17:02 -0700148}
149
egdaniel9cf45bf2014-10-08 06:49:10 -0700150void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds,
joshualitt79f8fae2014-10-28 17:59:26 -0700151 GrProgramDesc::DescInfo* descInfo,
egdaniel9cf45bf2014-10-08 06:49:10 -0700152 int* firstColorStageIdx,
153 int* firstCoverageStageIdx,
154 uint8_t* fixedFunctionVAToRemove) {
egdaniel170f90b2014-09-16 12:54:40 -0700155 switch (fBlendOptFlags) {
156 case kNone_BlendOpt:
157 case kSkipDraw_BlendOptFlag:
158 break;
159 case kCoverageAsAlpha_BlendOptFlag:
160 fFlagBits |= kCoverageDrawing_StateBit;
161 break;
162 case kEmitCoverage_BlendOptFlag:
163 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700164 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700165 *firstColorStageIdx = ds.numColorStages();
166 *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
egdaniel170f90b2014-09-16 12:54:40 -0700167 break;
168 case kEmitTransBlack_BlendOptFlag:
169 fColor = 0;
170 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700171 descInfo->fInputColorIsUsed = true;
172 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700173 *firstColorStageIdx = ds.numColorStages();
174 *firstCoverageStageIdx = ds.numCoverageStages();
175 *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
176 0x1 << kCoverage_GrVertexAttribBinding);
egdaniel170f90b2014-09-16 12:54:40 -0700177 break;
178 default:
179 SkFAIL("Unknown BlendOptFlag");
egdaniel170f90b2014-09-16 12:54:40 -0700180 }
181}
182
joshualitt79f8fae2014-10-28 17:59:26 -0700183void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag,
184 GrProgramDesc::DescInfo* descInfo) {
egdaniel3658f382014-09-15 07:01:59 -0700185 int numToRemove = 0;
186 uint8_t maskCheck = 0x1;
187 // Count the number of vertex attributes that we will actually remove
188 for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
joshualitt79f8fae2014-10-28 17:59:26 -0700189 if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) {
egdaniel3658f382014-09-15 07:01:59 -0700190 ++numToRemove;
191 }
192 maskCheck <<= 1;
193 }
egdaniel170f90b2014-09-16 12:54:40 -0700194
egdaniel3658f382014-09-15 07:01:59 -0700195 fOptVA.reset(fVACount - numToRemove);
196
197 GrVertexAttrib* dst = fOptVA.get();
198 const GrVertexAttrib* src = fVAPtr;
199
200 for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
201 const GrVertexAttrib& currAttrib = *src;
202 if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
203 uint8_t maskCheck = 0x1 << currAttrib.fBinding;
204 if (maskCheck & removeVAFlag) {
joshualitt79f8fae2014-10-28 17:59:26 -0700205 SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
206 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
egdaniel3658f382014-09-15 07:01:59 -0700207 continue;
208 }
joshualitt79f8fae2014-10-28 17:59:26 -0700209 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
egdaniel3658f382014-09-15 07:01:59 -0700210 }
211 memcpy(dst, src, sizeof(GrVertexAttrib));
egdaniel3658f382014-09-15 07:01:59 -0700212 ++newIdx;
213 ++dst;
214 }
215 fVACount -= numToRemove;
216 fVAPtr = fOptVA.get();
217}
218
joshualittb0a8a372014-09-23 09:50:21 -0700219static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700220 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700221 *readsDst = true;
222 }
joshualitt47bb3822014-10-07 16:43:25 -0700223 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700224 *readsFragPosition = true;
225 }
226}
joshualittb0a8a372014-09-23 09:50:21 -0700227
egdaniel9cf45bf2014-10-08 06:49:10 -0700228void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt79f8fae2014-10-28 17:59:26 -0700229 int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700230 // We will need a local coord attrib if there is one currently set on the optState and we are
231 // actually generating some effect code
joshualitt79f8fae2014-10-28 17:59:26 -0700232 descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700233 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700234
joshualitt79f8fae2014-10-28 17:59:26 -0700235 descInfo->fReadsDst = false;
236 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700237
egdaniel9cf45bf2014-10-08 06:49:10 -0700238 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
239 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700240 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700241 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700242 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
243 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700244 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700245 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700246 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700247 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700248 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700249 }
250}
251
egdaniel89af44a2014-09-26 06:15:04 -0700252////////////////////////////////////////////////////////////////////////////////
253
egdaniel3658f382014-09-15 07:01:59 -0700254bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700255 if (this->fDesc != that.fDesc) {
256 return false;
257 }
258 bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700259 if (!usingVertexColors && this->fColor != that.fColor) {
260 return false;
261 }
262
263 if (this->getRenderTarget() != that.getRenderTarget() ||
egdaniel89af44a2014-09-26 06:15:04 -0700264 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
265 this->fSrcBlend != that.fSrcBlend ||
266 this->fDstBlend != that.fDstBlend ||
267 this->fBlendConstant != that.fBlendConstant ||
268 this->fFlagBits != that.fFlagBits ||
269 this->fVACount != that.fVACount ||
270 this->fVAStride != that.fVAStride ||
271 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
272 this->fStencilSettings != that.fStencilSettings ||
joshualitt79f8fae2014-10-28 17:59:26 -0700273 this->fDrawFace != that.fDrawFace) {
egdaniel89af44a2014-09-26 06:15:04 -0700274 return false;
275 }
276
joshualitt79f8fae2014-10-28 17:59:26 -0700277 bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1;
egdaniel89af44a2014-09-26 06:15:04 -0700278 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
279 return false;
280 }
281
egdaniel89af44a2014-09-26 06:15:04 -0700282 if (this->hasGeometryProcessor()) {
283 if (!that.hasGeometryProcessor()) {
284 return false;
joshualitta5305a12014-10-10 17:47:00 -0700285 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700286 return false;
287 }
288 } else if (that.hasGeometryProcessor()) {
289 return false;
290 }
291
bsalomonae59b772014-11-19 08:23:49 -0800292 // The program desc comparison should have already assured that the stage counts match.
293 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700294 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800295
296 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700297 return false;
298 }
299 }
egdaniel89af44a2014-09-26 06:15:04 -0700300 return true;
301}
302