blob: 41a34c4ed2d885bedb7653d1152704e4cf3dd8bf [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
bsalomonae59b772014-11-19 08:23:49 -0800103 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800104 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
105 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
106 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800107 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800108 }
egdanield9aa2182014-10-09 13:47:05 -0700109 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800110 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
111 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
112 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800113 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700114 }
joshualitt79f8fae2014-10-28 17:59:26 -0700115
bsalomon04ddf892014-11-19 12:36:22 -0800116 this->setOutputStateInfo(drawState, blendOpt, *gpu->caps(), &descInfo);
joshualitt4dd99882014-11-11 08:51:30 -0800117
joshualitt79f8fae2014-10-28 17:59:26 -0700118 // now create a key
joshualitt9176e2c2014-11-20 07:28:52 -0800119 gpu->buildProgramDesc(*this, descInfo, drawType, &fDesc);
egdaniel3658f382014-09-15 07:01:59 -0700120};
121
egdaniel9cf45bf2014-10-08 06:49:10 -0700122void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
bsalomon04ddf892014-11-19 12:36:22 -0800123 GrDrawState::BlendOpt blendOpt,
egdaniel9cf45bf2014-10-08 06:49:10 -0700124 const GrDrawTargetCaps& caps,
joshualitt4dd99882014-11-11 08:51:30 -0800125 GrProgramDesc::DescInfo* descInfo) {
egdanielc0648242014-09-22 13:17:02 -0700126 // Set this default and then possibly change our mind if there is coverage.
joshualitt79f8fae2014-10-28 17:59:26 -0700127 descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
128 descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700129
bsalomon04ddf892014-11-19 12:36:22 -0800130 // Determine whether we should use dual source blending or shader code to keep coverage
131 // separate from color.
132 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blendOpt ||
133 GrDrawState::kEmitCoverage_BlendOpt == blendOpt);
134 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700135 if (caps.dualSourceBlendingSupport()) {
136 if (kZero_GrBlendCoeff == fDstBlend) {
137 // write the coverage value to second color
joshualitt79f8fae2014-10-28 17:59:26 -0700138 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700139 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
140 } else if (kSA_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::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700143 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
144 } else if (kSC_GrBlendCoeff == fDstBlend) {
145 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualitt79f8fae2014-10-28 17:59:26 -0700146 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700147 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
148 }
joshualitt79f8fae2014-10-28 17:59:26 -0700149 } else if (descInfo->fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700150 kOne_GrBlendCoeff == fSrcBlend &&
151 kZero_GrBlendCoeff == fDstBlend) {
joshualitt79f8fae2014-10-28 17:59:26 -0700152 descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700153 }
154 }
egdanielc0648242014-09-22 13:17:02 -0700155}
156
bsalomon04ddf892014-11-19 12:36:22 -0800157void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds,
158 GrDrawState::BlendOpt blendOpt,
159 GrProgramDesc::DescInfo* descInfo,
160 int* firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800161 int* firstCoverageStageIdx) {
bsalomon04ddf892014-11-19 12:36:22 -0800162 switch (blendOpt) {
163 case GrDrawState::kNone_BlendOpt:
164 case GrDrawState::kSkipDraw_BlendOpt:
165 case GrDrawState::kCoverageAsAlpha_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700166 break;
bsalomon04ddf892014-11-19 12:36:22 -0800167 case GrDrawState::kEmitCoverage_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700168 fColor = 0xffffffff;
joshualitt79f8fae2014-10-28 17:59:26 -0700169 descInfo->fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700170 *firstColorStageIdx = ds.numColorStages();
joshualitt2dd1ae02014-12-03 06:24:10 -0800171 descInfo->fHasVertexColor = false;
egdaniel170f90b2014-09-16 12:54:40 -0700172 break;
bsalomon04ddf892014-11-19 12:36:22 -0800173 case GrDrawState::kEmitTransBlack_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700174 fColor = 0;
175 fCoverage = 0xff;
joshualitt79f8fae2014-10-28 17:59:26 -0700176 descInfo->fInputColorIsUsed = true;
177 descInfo->fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700178 *firstColorStageIdx = ds.numColorStages();
179 *firstCoverageStageIdx = ds.numCoverageStages();
joshualitt2dd1ae02014-12-03 06:24:10 -0800180 descInfo->fHasVertexColor = false;
181 descInfo->fHasVertexCoverage = false;
egdaniel170f90b2014-09-16 12:54:40 -0700182 break;
egdaniel170f90b2014-09-16 12:54:40 -0700183 }
184}
185
joshualittb0a8a372014-09-23 09:50:21 -0700186static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700187 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700188 *readsDst = true;
189 }
joshualitt47bb3822014-10-07 16:43:25 -0700190 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700191 *readsFragPosition = true;
192 }
193}
joshualittb0a8a372014-09-23 09:50:21 -0700194
egdaniel9cf45bf2014-10-08 06:49:10 -0700195void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800196 int firstCoverageStageIdx, bool hasLocalCoords,
197 GrProgramDesc::DescInfo* descInfo) {
egdaniela7dc0a82014-09-17 08:25:05 -0700198 // We will need a local coord attrib if there is one currently set on the optState and we are
199 // actually generating some effect code
joshualitt2dd1ae02014-12-03 06:24:10 -0800200 descInfo->fRequiresLocalCoordAttrib = hasLocalCoords &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700201 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700202
joshualitt79f8fae2014-10-28 17:59:26 -0700203 descInfo->fReadsDst = false;
204 descInfo->fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700205
egdaniel9cf45bf2014-10-08 06:49:10 -0700206 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
207 const GrFragmentStage& stage = ds.getColorStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700208 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700209 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700210 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
211 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualitt79f8fae2014-10-28 17:59:26 -0700212 get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700213 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700214 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700215 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualitt79f8fae2014-10-28 17:59:26 -0700216 descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700217 }
218}
219
egdaniel89af44a2014-09-26 06:15:04 -0700220////////////////////////////////////////////////////////////////////////////////
221
egdaniel3658f382014-09-15 07:01:59 -0700222bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualitt79f8fae2014-10-28 17:59:26 -0700223 if (this->fDesc != that.fDesc) {
224 return false;
225 }
joshualitt2dd1ae02014-12-03 06:24:10 -0800226 bool hasVertexColors = this->fDesc.header().fColorInput == GrProgramDesc::kAttribute_ColorInput;
227 if (!hasVertexColors && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700228 return false;
229 }
230
231 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualitt54e0c122014-11-19 09:38:51 -0800232 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700233 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
234 this->fSrcBlend != that.fSrcBlend ||
235 this->fDstBlend != that.fDstBlend ||
236 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800237 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700238 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800239 this->fDrawFace != that.fDrawFace ||
240 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700241 return false;
242 }
243
joshualitt2dd1ae02014-12-03 06:24:10 -0800244 bool hasVertexCoverage =
245 this->fDesc.header().fCoverageInput == GrProgramDesc::kAttribute_ColorInput;
246 if (!hasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700247 return false;
248 }
249
egdaniel89af44a2014-09-26 06:15:04 -0700250 if (this->hasGeometryProcessor()) {
251 if (!that.hasGeometryProcessor()) {
252 return false;
joshualitta5305a12014-10-10 17:47:00 -0700253 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700254 return false;
255 }
256 } else if (that.hasGeometryProcessor()) {
257 return false;
258 }
259
bsalomonae59b772014-11-19 08:23:49 -0800260 // The program desc comparison should have already assured that the stage counts match.
261 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700262 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800263
264 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700265 return false;
266 }
267 }
egdaniel89af44a2014-09-26 06:15:04 -0700268 return true;
269}
270