blob: b7875968135b4703fb323e0d995d5acf33f33b07 [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);
joshualitt841a6b52014-12-04 06:00:41 -0800120};
egdaniel3658f382014-09-15 07:01:59 -0700121
egdaniel9cf45bf2014-10-08 06:49:10 -0700122void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
bsalomon04ddf892014-11-19 12:36:22 -0800123 GrDrawState::BlendOpt blendOpt,
joshualittdafa4d02014-12-04 08:59:10 -0800124 const GrDrawTargetCaps& caps) {
egdanielc0648242014-09-22 13:17:02 -0700125 // Set this default and then possibly change our mind if there is coverage.
joshualittdafa4d02014-12-04 08:59:10 -0800126 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
127 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700128
bsalomon04ddf892014-11-19 12:36:22 -0800129 // Determine whether we should use dual source blending or shader code to keep coverage
130 // separate from color.
131 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blendOpt ||
132 GrDrawState::kEmitCoverage_BlendOpt == blendOpt);
133 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700134 if (caps.dualSourceBlendingSupport()) {
135 if (kZero_GrBlendCoeff == fDstBlend) {
136 // write the coverage value to second color
joshualittdafa4d02014-12-04 08:59:10 -0800137 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700138 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
139 } else if (kSA_GrBlendCoeff == fDstBlend) {
140 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800141 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700142 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
143 } else if (kSC_GrBlendCoeff == fDstBlend) {
144 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800145 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700146 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
147 }
joshualittdafa4d02014-12-04 08:59:10 -0800148 } else if (fDescInfo.fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700149 kOne_GrBlendCoeff == fSrcBlend &&
150 kZero_GrBlendCoeff == fDstBlend) {
joshualittdafa4d02014-12-04 08:59:10 -0800151 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700152 }
153 }
egdanielc0648242014-09-22 13:17:02 -0700154}
155
bsalomon04ddf892014-11-19 12:36:22 -0800156void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds,
157 GrDrawState::BlendOpt blendOpt,
bsalomon04ddf892014-11-19 12:36:22 -0800158 int* firstColorStageIdx,
joshualitt2dd1ae02014-12-03 06:24:10 -0800159 int* firstCoverageStageIdx) {
bsalomon04ddf892014-11-19 12:36:22 -0800160 switch (blendOpt) {
161 case GrDrawState::kNone_BlendOpt:
162 case GrDrawState::kSkipDraw_BlendOpt:
163 case GrDrawState::kCoverageAsAlpha_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700164 break;
bsalomon04ddf892014-11-19 12:36:22 -0800165 case GrDrawState::kEmitCoverage_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700166 fColor = 0xffffffff;
joshualittdafa4d02014-12-04 08:59:10 -0800167 fDescInfo.fInputColorIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700168 *firstColorStageIdx = ds.numColorStages();
joshualittdafa4d02014-12-04 08:59:10 -0800169 fDescInfo.fHasVertexColor = false;
egdaniel170f90b2014-09-16 12:54:40 -0700170 break;
bsalomon04ddf892014-11-19 12:36:22 -0800171 case GrDrawState::kEmitTransBlack_BlendOpt:
egdaniel170f90b2014-09-16 12:54:40 -0700172 fColor = 0;
173 fCoverage = 0xff;
joshualittdafa4d02014-12-04 08:59:10 -0800174 fDescInfo.fInputColorIsUsed = true;
175 fDescInfo.fInputCoverageIsUsed = true;
egdaniel9cf45bf2014-10-08 06:49:10 -0700176 *firstColorStageIdx = ds.numColorStages();
177 *firstCoverageStageIdx = ds.numCoverageStages();
joshualittdafa4d02014-12-04 08:59:10 -0800178 fDescInfo.fHasVertexColor = false;
179 fDescInfo.fHasVertexCoverage = false;
egdaniel170f90b2014-09-16 12:54:40 -0700180 break;
egdaniel170f90b2014-09-16 12:54:40 -0700181 }
182}
183
joshualittb0a8a372014-09-23 09:50:21 -0700184static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
joshualitt47bb3822014-10-07 16:43:25 -0700185 if (stage.getProcessor()->willReadDstColor()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700186 *readsDst = true;
187 }
joshualitt47bb3822014-10-07 16:43:25 -0700188 if (stage.getProcessor()->willReadFragmentPosition()) {
egdaniela7dc0a82014-09-17 08:25:05 -0700189 *readsFragPosition = true;
190 }
191}
joshualittb0a8a372014-09-23 09:50:21 -0700192
egdaniel9cf45bf2014-10-08 06:49:10 -0700193void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
joshualittdafa4d02014-12-04 08:59:10 -0800194 int firstCoverageStageIdx, bool hasLocalCoords) {
egdaniela7dc0a82014-09-17 08:25:05 -0700195 // We will need a local coord attrib if there is one currently set on the optState and we are
196 // actually generating some effect code
joshualittdafa4d02014-12-04 08:59:10 -0800197 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords &&
egdaniel9cf45bf2014-10-08 06:49:10 -0700198 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
egdaniela7dc0a82014-09-17 08:25:05 -0700199
joshualittdafa4d02014-12-04 08:59:10 -0800200 fDescInfo.fReadsDst = false;
201 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700202
egdaniel9cf45bf2014-10-08 06:49:10 -0700203 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
204 const GrFragmentStage& stage = ds.getColorStage(s);
joshualittdafa4d02014-12-04 08:59:10 -0800205 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700206 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700207 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
208 const GrFragmentStage& stage = ds.getCoverageStage(s);
joshualittdafa4d02014-12-04 08:59:10 -0800209 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPosition);
egdaniela7dc0a82014-09-17 08:25:05 -0700210 }
egdaniel9cf45bf2014-10-08 06:49:10 -0700211 if (ds.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700212 const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
joshualittdafa4d02014-12-04 08:59:10 -0800213 fDescInfo.fReadsFragPosition = fDescInfo.fReadsFragPosition || gp.willReadFragmentPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700214 }
215}
216
joshualittdafa4d02014-12-04 08:59:10 -0800217void GrOptDrawState::finalize(GrGpu* gpu) {
218 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
219 fFinalized = true;
220}
221
egdaniel89af44a2014-09-26 06:15:04 -0700222////////////////////////////////////////////////////////////////////////////////
223
egdaniel3658f382014-09-15 07:01:59 -0700224bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800225 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800226 return false;
227 }
joshualittdafa4d02014-12-04 08:59:10 -0800228
229 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700230 return false;
231 }
232
233 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800234 this->fFragmentStages.count() != that.fFragmentStages.count() ||
235 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800236 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700237 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
238 this->fSrcBlend != that.fSrcBlend ||
239 this->fDstBlend != that.fDstBlend ||
joshualittdafa4d02014-12-04 08:59:10 -0800240 this->fDrawType != that.fDrawType ||
egdaniel89af44a2014-09-26 06:15:04 -0700241 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
joshualittdafa4d02014-12-04 08:59:10 -0800249 if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700250 return false;
251 }
252
egdaniel89af44a2014-09-26 06:15:04 -0700253 if (this->hasGeometryProcessor()) {
254 if (!that.hasGeometryProcessor()) {
255 return false;
joshualitta5305a12014-10-10 17:47:00 -0700256 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700257 return false;
258 }
259 } else if (that.hasGeometryProcessor()) {
260 return false;
261 }
262
bsalomonae59b772014-11-19 08:23:49 -0800263 // The program desc comparison should have already assured that the stage counts match.
264 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700265 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800266
267 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700268 return false;
269 }
270 }
egdaniel89af44a2014-09-26 06:15:04 -0700271 return true;
272}
273