blob: d95bd3b7c42017a2526f4fd3e7fcb662bed8502e [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,
joshualittdafa4d02014-12-04 08:59:10 -080016 const GrDrawTargetCaps& caps,
joshualitt54e0c122014-11-19 09:38:51 -080017 const ScissorState& scissorState,
joshualitt79f8fae2014-10-28 17:59:26 -070018 const GrDeviceCoordTexture* dstCopy,
joshualittdafa4d02014-12-04 08:59:10 -080019 GrGpu::DrawType drawType)
20 : fFinalized(false) {
21 fDrawType = drawType;
bsalomonb03c4a32014-11-20 09:56:11 -080022 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;
bsalomonb03c4a32014-11-20 09:56:11 -080033 fDrawFace = GrDrawState::kInvalid_DrawFace;
34 fSrcBlend = kZero_GrBlendCoeff;
35 fDstBlend = kZero_GrBlendCoeff;
36 fBlendConstant = 0x0;
37 fViewMatrix.reset();
38 return;
39 }
40
41 fRenderTarget.reset(drawState.fRenderTarget.get());
42 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080043 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070044 fViewMatrix = drawState.getViewMatrix();
45 fBlendConstant = drawState.getBlendConstant();
egdaniel3658f382014-09-15 07:01:59 -070046 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080047 fDrawFace = drawState.getDrawFace();
egdaniel170f90b2014-09-16 12:54:40 -070048 fSrcBlend = optSrcCoeff;
49 fDstBlend = optDstCoeff;
joshualitt9176e2c2014-11-20 07:28:52 -080050
51 // TODO move this out of optDrawState
52 if (dstCopy) {
53 fDstCopy = *dstCopy;
54 }
55
bsalomon04ddf892014-11-19 12:36:22 -080056 fFlags = 0;
57 if (drawState.isHWAntialias()) {
58 fFlags |= kHWAA_Flag;
59 }
60 if (drawState.isColorWriteDisabled()) {
61 fFlags |= kDisableColorWrite_Flag;
62 }
63 if (drawState.isDither()) {
64 fFlags |= kDither_Flag;
65 }
66
joshualittdafa4d02014-12-04 08:59:10 -080067 fDescInfo.fHasVertexColor = drawState.hasGeometryProcessor() &&
68 drawState.getGeometryProcessor()->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -070069
joshualittdafa4d02014-12-04 08:59:10 -080070 fDescInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() &&
71 drawState.getGeometryProcessor()->hasVertexCoverage();
joshualitt2dd1ae02014-12-03 06:24:10 -080072
73 bool hasLocalCoords = drawState.hasGeometryProcessor() &&
74 drawState.getGeometryProcessor()->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -070075
egdaniel912b3d22014-11-17 07:45:53 -080076 const GrProcOptInfo& colorPOI = drawState.colorProcInfo();
77 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
joshualittdafa4d02014-12-04 08:59:10 -080078 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
egdaniel912b3d22014-11-17 07:45:53 -080079 fColor = colorPOI.inputColorToEffectiveStage();
80 if (colorPOI.removeVertexAttrib()) {
joshualittdafa4d02014-12-04 08:59:10 -080081 fDescInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -080082 }
83
84 // TODO: Once we can handle single or four channel input into coverage stages then we can use
85 // drawState's coverageProcInfo (like color above) to set this initial information.
86 int firstCoverageStageIdx = 0;
joshualittdafa4d02014-12-04 08:59:10 -080087 fDescInfo.fInputCoverageIsUsed = true;
egdaniel912b3d22014-11-17 07:45:53 -080088 fCoverage = drawState.getCoverage();
89
joshualittdafa4d02014-12-04 08:59:10 -080090 this->adjustProgramForBlendOpt(drawState, blendOpt, &firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -080091 &firstCoverageStageIdx);
92
joshualittdafa4d02014-12-04 08:59:10 -080093 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, hasLocalCoords);
egdaniel9cf45bf2014-10-08 06:49:10 -070094
95 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -080096 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
97 GrGpu::kStencilPath_DrawType ||
98 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -080099 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -0700100
egdaniel378092f2014-12-03 10:40:13 -0800101 // Create XferProcessor from DS's XPFactory
102 const GrXferProcessor* xpProcessor = drawState.getXPFactory()->createXferProcessor();
103 fXferProcessor.reset(xpProcessor);
104 xpProcessor->unref();
105
bsalomonae59b772014-11-19 08:23:49 -0800106 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800107 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
108 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
109 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800110 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800111 }
egdanield9aa2182014-10-09 13:47:05 -0700112 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800113 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
114 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
115 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800116 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700117 }
joshualitt79f8fae2014-10-28 17:59:26 -0700118
joshualittdafa4d02014-12-04 08:59:10 -0800119 this->setOutputStateInfo(drawState, blendOpt, caps);
joshualitt87f48d92014-12-04 10:41:40 -0800120
121 // let the GP init the batch tracker
122 if (drawState.hasGeometryProcessor()) {
123 GrGeometryProcessor::InitBT init;
124 init.fOutputColor = fDescInfo.fInputColorIsUsed;
125 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed;
126 init.fColor = this->getColor();
127 init.fCoverage = this->getCoverage();
128 fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
129 }
130}
egdaniel3658f382014-09-15 07:01:59 -0700131
egdaniel9cf45bf2014-10-08 06:49:10 -0700132void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
bsalomon04ddf892014-11-19 12:36:22 -0800133 GrDrawState::BlendOpt blendOpt,
joshualittdafa4d02014-12-04 08:59:10 -0800134 const GrDrawTargetCaps& caps) {
egdanielc0648242014-09-22 13:17:02 -0700135 // Set this default and then possibly change our mind if there is coverage.
joshualittdafa4d02014-12-04 08:59:10 -0800136 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
137 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700138
bsalomon04ddf892014-11-19 12:36:22 -0800139 // Determine whether we should use dual source blending or shader code to keep coverage
140 // separate from color.
141 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blendOpt ||
142 GrDrawState::kEmitCoverage_BlendOpt == blendOpt);
143 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700144 if (caps.dualSourceBlendingSupport()) {
145 if (kZero_GrBlendCoeff == fDstBlend) {
146 // write the coverage value to second color
joshualittdafa4d02014-12-04 08:59:10 -0800147 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700148 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
149 } else if (kSA_GrBlendCoeff == fDstBlend) {
150 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800151 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700152 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
153 } else if (kSC_GrBlendCoeff == fDstBlend) {
154 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800155 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700156 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
157 }
joshualittdafa4d02014-12-04 08:59:10 -0800158 } else if (fDescInfo.fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700159 kOne_GrBlendCoeff == fSrcBlend &&
160 kZero_GrBlendCoeff == fDstBlend) {
joshualittdafa4d02014-12-04 08:59:10 -0800161 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700162 }
163 }
egdanielc0648242014-09-22 13:17:02 -0700164}
165
bsalomon04ddf892014-11-19 12:36:22 -0800166void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds,
167 GrDrawState::BlendOpt blendOpt,
bsalomon04ddf892014-11-19 12:36:22 -0800168 int* firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800169 int* firstCoverageStageIdx) {
bsalomon04ddf892014-11-19 12:36:22 -0800170 switch (blendOpt) {
171 case GrDrawState::kNone_BlendOpt:
172 case GrDrawState::kSkipDraw_BlendOpt:
173 case GrDrawState::kCoverageAsAlpha_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700174 break;
bsalomon04ddf892014-11-19 12:36:22 -0800175 case GrDrawState::kEmitCoverage_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700176 fColor = 0xffffffff;
joshualittdafa4d02014-12-04 08:59:10 -0800177 fDescInfo.fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700178 *firstColorStageIdx = ds.numColorStages();
joshualittdafa4d02014-12-04 08:59:10 -0800179 fDescInfo.fHasVertexColor = false;
egdaniel170f90b2014-09-16 12:54:40 -0700180 break;
bsalomon04ddf892014-11-19 12:36:22 -0800181 case GrDrawState::kEmitTransBlack_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700182 fColor = 0;
183 fCoverage = 0xff;
joshualittdafa4d02014-12-04 08:59:10 -0800184 fDescInfo.fInputColorIsUsed = true;
185 fDescInfo.fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700186 *firstColorStageIdx = ds.numColorStages();
187 *firstCoverageStageIdx = ds.numCoverageStages();
joshualittdafa4d02014-12-04 08:59:10 -0800188 fDescInfo.fHasVertexColor = false;
189 fDescInfo.fHasVertexCoverage = false;
egdaniel170f90b2014-09-16 12:54:40 -0700190 break;
egdaniel170f90b2014-09-16 12:54:40 -0700191 }
192}
193
joshualittb0a8a372014-09-23 09:50:21 -0700194static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700195 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700196 *readsDst = true;
197 }
joshualitt47bb3822014-10-07 16:43:25 -0700198 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700199 *readsFragPosition = true;
200 }
201}
joshualittb0a8a372014-09-23 09:50:21 -0700202
egdaniel9cf45bf2014-10-08 06:49:10 -0700203void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualittdafa4d02014-12-04 08:59:10 -0800204 int firstCoverageStageIdx, bool hasLocalCoords) {
egdaniela7dc0a82014-09-17 08:25:05 -0700205 // We will need a local coord attrib if there is one currently set on the optState and we are
206 // actually generating some effect code
joshualittdafa4d02014-12-04 08:59:10 -0800207 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700208 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700209
joshualittdafa4d02014-12-04 08:59:10 -0800210 fDescInfo.fReadsDst = false;
211 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700212
egdaniel9cf45bf2014-10-08 06:49:10 -0700213 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
214 const GrFragmentStage& stage = ds.getColorStage(s);
joshualittdafa4d02014-12-04 08:59:10 -0800215 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700216 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700217 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
218 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualittdafa4d02014-12-04 08:59:10 -0800219 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700220 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700221 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700222 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualittdafa4d02014-12-04 08:59:10 -0800223 fDescInfo.fReadsFragPosition = fDescInfo.fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700224 }
225}
226
joshualittdafa4d02014-12-04 08:59:10 -0800227void GrOptDrawState::finalize(GrGpu* gpu) {
228 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
229 fFinalized = true;
230}
231
egdaniel89af44a2014-09-26 06:15:04 -0700232////////////////////////////////////////////////////////////////////////////////
233
egdaniel3658f382014-09-15 07:01:59 -0700234bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800235 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800236 return false;
237 }
joshualittdafa4d02014-12-04 08:59:10 -0800238
239 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700240 return false;
241 }
242
243 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800244 this->fFragmentStages.count() != that.fFragmentStages.count() ||
245 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800246 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700247 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
248 this->fSrcBlend != that.fSrcBlend ||
249 this->fDstBlend != that.fDstBlend ||
joshualittdafa4d02014-12-04 08:59:10 -0800250 this->fDrawType != that.fDrawType ||
egdaniel89af44a2014-09-26 06:15:04 -0700251 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800252 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700253 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800254 this->fDrawFace != that.fDrawFace ||
255 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700256 return false;
257 }
258
joshualittdafa4d02014-12-04 08:59:10 -0800259 if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700260 return false;
261 }
262
egdaniel89af44a2014-09-26 06:15:04 -0700263 if (this->hasGeometryProcessor()) {
264 if (!that.hasGeometryProcessor()) {
265 return false;
joshualitta5305a12014-10-10 17:47:00 -0700266 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700267 return false;
268 }
269 } else if (that.hasGeometryProcessor()) {
270 return false;
271 }
272
bsalomonae59b772014-11-19 08:23:49 -0800273 // The program desc comparison should have already assured that the stage counts match.
274 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700275 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800276
277 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700278 return false;
279 }
280 }
egdaniel89af44a2014-09-26 06:15:04 -0700281 return true;
282}
283