blob: 6f6f0af88821741649829ad680d488e15bdac12a [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
10#include "GrDrawState.h"
egdanielc0648242014-09-22 13:17:02 -070011#include "GrDrawTargetCaps.h"
joshualitt4973d9d2014-11-08 09:24:25 -080012#include "GrGpu.h"
egdanielb6cbc382014-11-13 11:00:34 -080013#include "GrProcOptInfo.h"
egdaniel3658f382014-09-15 07:01:59 -070014
egdaniel170f90b2014-09-16 12:54:40 -070015GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
joshualitt79f8fae2014-10-28 17:59:26 -070016 GrGpu* gpu,
joshualitt54e0c122014-11-19 09:38:51 -080017 const ScissorState& scissorState,
joshualitt79f8fae2014-10-28 17:59:26 -070018 const GrDeviceCoordTexture* dstCopy,
bsalomonb03c4a32014-11-20 09:56:11 -080019 GrGpu::DrawType drawType) {
20
21 GrBlendCoeff optSrcCoeff;
22 GrBlendCoeff optDstCoeff;
23 GrDrawState::BlendOpt blendOpt = drawState.getBlendOpt(false, &optSrcCoeff, &optDstCoeff);
24
25 // When path rendering the stencil settings are not always set on the draw state
26 // so we must check the draw type. In cases where we will skip drawing we simply return a
27 // null GrOptDrawState.
28 if (GrDrawState::kSkipDraw_BlendOpt == blendOpt && GrGpu::kStencilPath_DrawType != drawType) {
29 // Set the fields that don't default init and return. The lack of a render target will
30 // indicate that this can be skipped.
31 fFlags = 0;
bsalomonb03c4a32014-11-20 09:56:11 -080032 fDrawFace = GrDrawState::kInvalid_DrawFace;
33 fSrcBlend = kZero_GrBlendCoeff;
34 fDstBlend = kZero_GrBlendCoeff;
35 fBlendConstant = 0x0;
36 fViewMatrix.reset();
37 return;
38 }
39
40 fRenderTarget.reset(drawState.fRenderTarget.get());
41 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080042 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070043 fViewMatrix = drawState.getViewMatrix();
44 fBlendConstant = drawState.getBlendConstant();
egdaniel3658f382014-09-15 07:01:59 -070045 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080046 fDrawFace = drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070047 fSrcBlend = optSrcCoeff;
48 fDstBlend = optDstCoeff;
joshualitt9176e2c2014-11-20 07:28:52 -080049
50 // TODO move this out of optDrawState
51 if (dstCopy) {
52 fDstCopy = *dstCopy;
53 }
54
joshualitt79f8fae2014-10-28 17:59:26 -070055 GrProgramDesc::DescInfo descInfo;
egdaniel3658f382014-09-15 07:01:59 -070056
bsalomon04ddf892014-11-19 12:36:22 -080057 fFlags = 0;
58 if (drawState.isHWAntialias()) {
59 fFlags |= kHWAA_Flag;
60 }
61 if (drawState.isColorWriteDisabled()) {
62 fFlags |= kDisableColorWrite_Flag;
63 }
64 if (drawState.isDither()) {
65 fFlags |= kDither_Flag;
66 }
67
joshualitt2dd1ae02014-12-03 06:24:10 -080068 descInfo.fHasVertexColor = drawState.hasGeometryProcessor() &&
69 drawState.getGeometryProcessor()->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -070070
joshualitt2dd1ae02014-12-03 06:24:10 -080071 descInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() &&
72 drawState.getGeometryProcessor()->hasVertexCoverage();
73
74 bool hasLocalCoords = drawState.hasGeometryProcessor() &&
75 drawState.getGeometryProcessor()->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -070076
egdaniel912b3d22014-11-17 07:45:53 -080077 const GrProcOptInfo& colorPOI = drawState.colorProcInfo();
78 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
79 descInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
80 fColor = colorPOI.inputColorToEffectiveStage();
81 if (colorPOI.removeVertexAttrib()) {
joshualitt2dd1ae02014-12-03 06:24:10 -080082 descInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -080083 }
84
85 // TODO: Once we can handle single or four channel input into coverage stages then we can use
86 // drawState's coverageProcInfo (like color above) to set this initial information.
87 int firstCoverageStageIdx = 0;
88 descInfo.fInputCoverageIsUsed = true;
89 fCoverage = drawState.getCoverage();
90
bsalomon04ddf892014-11-19 12:36:22 -080091 this->adjustProgramForBlendOpt(drawState, blendOpt, &descInfo, &firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -080092 &firstCoverageStageIdx);
93
94 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, hasLocalCoords,
95 &descInfo);
egdaniel9cf45bf2014-10-08 06:49:10 -070096
97 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -080098 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
99 GrGpu::kStencilPath_DrawType ||
100 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -0800101 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -0700102
egdaniel378092f2014-12-03 10:40:13 -0800103 // Create XferProcessor from DS's XPFactory
104 const GrXferProcessor* xpProcessor = drawState.getXPFactory()->createXferProcessor();
105 fXferProcessor.reset(xpProcessor);
106 xpProcessor->unref();
107
bsalomonae59b772014-11-19 08:23:49 -0800108 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800109 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
110 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
111 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800112 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800113 }
egdanield9aa2182014-10-09 13:47:05 -0700114 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800115 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
116 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
117 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800118 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700119 }
joshualitt79f8fae2014-10-28 17:59:26 -0700120
bsalomon04ddf892014-11-19 12:36:22 -0800121 this->setOutputStateInfo(drawState, blendOpt, *gpu->caps(), &descInfo);
joshualitt4dd99882014-11-11 08:51:30 -0800122
joshualitt79f8fae2014-10-28 17:59:26 -0700123 // now create a key
joshualitt9176e2c2014-11-20 07:28:52 -0800124 gpu->buildProgramDesc(*this, descInfo, drawType, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -0700125};
126
egdaniel9cf45bf2014-10-08 06:49:10 -0700127void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
bsalomon04ddf892014-11-19 12:36:22 -0800128 GrDrawState::BlendOpt blendOpt,
egdaniel9cf45bf2014-10-08 06:49:10 -0700129 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800130 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700131 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700132 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
133 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700134
bsalomon04ddf892014-11-19 12:36:22 -0800135 // Determine whether we should use dual source blending or shader code to keep coverage
136 // separate from color.
137 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blendOpt ||
138 GrDrawState::kEmitCoverage_BlendOpt == blendOpt);
139 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700140 if (caps.dualSourceBlendingSupport()) {
141 if (kZero_GrBlendCoeff == fDstBlend) {
142 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700143 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700144 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
145 } else if (kSA_GrBlendCoeff == fDstBlend) {
146 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700147 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700148 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
149 } else if (kSC_GrBlendCoeff == fDstBlend) {
150 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700151 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700152 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
153 }
joshualitt79f8fae2014-10-28 17:59:26 -0700154 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700155 kOne_GrBlendCoeff == fSrcBlend &&
156 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700157 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700158 }
159 }
egdanielc0648242014-09-22 13:17:02 -0700160}
161
bsalomon04ddf892014-11-19 12:36:22 -0800162void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds,
163 GrDrawState::BlendOpt blendOpt,
164 GrProgramDesc::DescInfo* descInfo,
165 int* firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800166 int* firstCoverageStageIdx) {
bsalomon04ddf892014-11-19 12:36:22 -0800167 switch (blendOpt) {
168 case GrDrawState::kNone_BlendOpt:
169 case GrDrawState::kSkipDraw_BlendOpt:
170 case GrDrawState::kCoverageAsAlpha_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700171 break;
bsalomon04ddf892014-11-19 12:36:22 -0800172 case GrDrawState::kEmitCoverage_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700173 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700174 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700175 *firstColorStageIdx = ds.numColorStages();
joshualitt2dd1ae02014-12-03 06:24:10 -0800176 descInfo->fHasVertexColor = false;
egdaniel170f90b2014-09-16 12:54:40 -0700177 break;
bsalomon04ddf892014-11-19 12:36:22 -0800178 case GrDrawState::kEmitTransBlack_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700179 fColor = 0;
180 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700181 descInfo->fInputColorIsUsed = true;
182 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700183 *firstColorStageIdx = ds.numColorStages();
184 *firstCoverageStageIdx = ds.numCoverageStages();
joshualitt2dd1ae02014-12-03 06:24:10 -0800185 descInfo->fHasVertexColor = false;
186 descInfo->fHasVertexCoverage = false;
egdaniel170f90b2014-09-16 12:54:40 -0700187 break;
egdaniel170f90b2014-09-16 12:54:40 -0700188 }
189}
190
joshualittb0a8a372014-09-23 09:50:21 -0700191static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700192 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700193 *readsDst = true;
194 }
joshualitt47bb3822014-10-07 16:43:25 -0700195 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700196 *readsFragPosition = true;
197 }
198}
joshualittb0a8a372014-09-23 09:50:21 -0700199
egdaniel9cf45bf2014-10-08 06:49:10 -0700200void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800201 int firstCoverageStageIdx, bool hasLocalCoords,
202 GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700203 // We will need a local coord attrib if there is one currently set on the optState and we are
204 // actually generating some effect code
joshualitt2dd1ae02014-12-03 06:24:10 -0800205 descInfo->fRequiresLocalCoordAttrib = hasLocalCoords &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700206 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700207
joshualitt79f8fae2014-10-28 17:59:26 -0700208 descInfo->fReadsDst = false;
209 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700210
egdaniel9cf45bf2014-10-08 06:49:10 -0700211 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
212 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700213 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700214 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700215 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
216 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700217 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700218 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700219 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700220 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700221 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700222 }
223}
224
egdaniel89af44a2014-09-26 06:15:04 -0700225////////////////////////////////////////////////////////////////////////////////
226
egdaniel3658f382014-09-15 07:01:59 -0700227bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700228 if (this->fDesc != that.fDesc) {
229 return false;
230 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800231 bool hasVertexColors = this->fDesc.header().fColorInput == GrProgramDesc::kAttribute_ColorInput;
232 if (!hasVertexColors && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700233 return false;
234 }
235
236 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualitt54e0c122014-11-19 09:38:51 -0800237 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700238 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
239 this->fSrcBlend != that.fSrcBlend ||
240 this->fDstBlend != that.fDstBlend ||
241 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800242 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700243 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800244 this->fDrawFace != that.fDrawFace ||
245 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700246 return false;
247 }
248
joshualitt2dd1ae02014-12-03 06:24:10 -0800249 bool hasVertexCoverage =
250 this->fDesc.header().fCoverageInput == GrProgramDesc::kAttribute_ColorInput;
251 if (!hasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700252 return false;
253 }
254
egdaniel89af44a2014-09-26 06:15:04 -0700255 if (this->hasGeometryProcessor()) {
256 if (!that.hasGeometryProcessor()) {
257 return false;
joshualitta5305a12014-10-10 17:47:00 -0700258 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700259 return false;
260 }
261 } else if (that.hasGeometryProcessor()) {
262 return false;
263 }
264
bsalomonae59b772014-11-19 08:23:49 -0800265 // The program desc comparison should have already assured that the stage counts match.
266 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700267 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800268
269 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700270 return false;
271 }
272 }
egdaniel89af44a2014-09-26 06:15:04 -0700273 return true;
274}
275