blob: 409305ce33fae912d79acbd2f3964ed589d4464a [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"
egdaniel95131432014-12-09 11:15:43 -080014#include "GrXferProcessor.h"
egdaniel3658f382014-09-15 07:01:59 -070015
egdaniel170f90b2014-09-16 12:54:40 -070016GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
joshualitt2e3b3e32014-12-09 13:31:14 -080017 GrColor color,
18 uint8_t coverage,
joshualittdafa4d02014-12-04 08:59:10 -080019 const GrDrawTargetCaps& caps,
joshualitt54e0c122014-11-19 09:38:51 -080020 const ScissorState& scissorState,
joshualitt79f8fae2014-10-28 17:59:26 -070021 const GrDeviceCoordTexture* dstCopy,
joshualittdafa4d02014-12-04 08:59:10 -080022 GrGpu::DrawType drawType)
23 : fFinalized(false) {
joshualitt2e3b3e32014-12-09 13:31:14 -080024 GrColor coverageColor = GrColorPackRGBA(coverage, coverage, coverage, coverage);
joshualittdafa4d02014-12-04 08:59:10 -080025 fDrawType = drawType;
egdaniel95131432014-12-09 11:15:43 -080026
joshualitt2e3b3e32014-12-09 13:31:14 -080027 const GrProcOptInfo& colorPOI = drawState.colorProcInfo(color);
28 const GrProcOptInfo& coveragePOI = drawState.coverageProcInfo(coverageColor);
egdaniel95131432014-12-09 11:15:43 -080029
30 fColor = colorPOI.inputColorToEffectiveStage();
joshualitt2e3b3e32014-12-09 13:31:14 -080031 fCoverage = coverage;
egdaniel95131432014-12-09 11:15:43 -080032
33 // Create XferProcessor from DS's XPFactory
34 SkAutoTUnref<GrXferProcessor> xferProcessor(
35 drawState.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
36
37 GrXferProcessor::OptFlags optFlags;
38 if (xferProcessor) {
39 fXferProcessor.reset(xferProcessor.get());
40
41 optFlags = xferProcessor->getOptimizations(colorPOI,
42 coveragePOI,
43 drawState.isCoverageDrawing(),
44 drawState.isColorWriteDisabled(),
45 drawState.getStencil().doesWrite(),
46 &fColor,
47 &fCoverage);
48 }
bsalomonb03c4a32014-11-20 09:56:11 -080049
50 // When path rendering the stencil settings are not always set on the draw state
51 // so we must check the draw type. In cases where we will skip drawing we simply return a
52 // null GrOptDrawState.
egdaniel95131432014-12-09 11:15:43 -080053 if (!xferProcessor || ((GrXferProcessor::kSkipDraw_OptFlag & optFlags) &&
54 GrGpu::kStencilPath_DrawType != drawType)) {
bsalomonb03c4a32014-11-20 09:56:11 -080055 // Set the fields that don't default init and return. The lack of a render target will
56 // indicate that this can be skipped.
57 fFlags = 0;
bsalomonb03c4a32014-11-20 09:56:11 -080058 fDrawFace = GrDrawState::kInvalid_DrawFace;
59 fSrcBlend = kZero_GrBlendCoeff;
60 fDstBlend = kZero_GrBlendCoeff;
61 fBlendConstant = 0x0;
62 fViewMatrix.reset();
63 return;
64 }
65
66 fRenderTarget.reset(drawState.fRenderTarget.get());
67 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080068 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070069 fViewMatrix = drawState.getViewMatrix();
egdaniel3658f382014-09-15 07:01:59 -070070 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080071 fDrawFace = drawState.getDrawFace();
joshualitt9176e2c2014-11-20 07:28:52 -080072 // TODO move this out of optDrawState
73 if (dstCopy) {
74 fDstCopy = *dstCopy;
75 }
76
bsalomon04ddf892014-11-19 12:36:22 -080077 fFlags = 0;
78 if (drawState.isHWAntialias()) {
79 fFlags |= kHWAA_Flag;
80 }
81 if (drawState.isColorWriteDisabled()) {
82 fFlags |= kDisableColorWrite_Flag;
83 }
84 if (drawState.isDither()) {
85 fFlags |= kDither_Flag;
86 }
87
joshualittdafa4d02014-12-04 08:59:10 -080088 fDescInfo.fHasVertexColor = drawState.hasGeometryProcessor() &&
89 drawState.getGeometryProcessor()->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -070090
joshualittdafa4d02014-12-04 08:59:10 -080091 fDescInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() &&
92 drawState.getGeometryProcessor()->hasVertexCoverage();
joshualitt2dd1ae02014-12-03 06:24:10 -080093
94 bool hasLocalCoords = drawState.hasGeometryProcessor() &&
95 drawState.getGeometryProcessor()->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -070096
egdaniel912b3d22014-11-17 07:45:53 -080097 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
joshualittdafa4d02014-12-04 08:59:10 -080098 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
egdaniel912b3d22014-11-17 07:45:53 -080099 if (colorPOI.removeVertexAttrib()) {
joshualittdafa4d02014-12-04 08:59:10 -0800100 fDescInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -0800101 }
102
103 // TODO: Once we can handle single or four channel input into coverage stages then we can use
104 // drawState's coverageProcInfo (like color above) to set this initial information.
105 int firstCoverageStageIdx = 0;
joshualittdafa4d02014-12-04 08:59:10 -0800106 fDescInfo.fInputCoverageIsUsed = true;
egdaniel912b3d22014-11-17 07:45:53 -0800107
joshualitt2dd1ae02014-12-03 06:24:10 -0800108
egdaniel95131432014-12-09 11:15:43 -0800109 GrXferProcessor::BlendInfo blendInfo;
110 fXferProcessor->getBlendInfo(&blendInfo);
111 fSrcBlend = blendInfo.fSrcBlend;
112 fDstBlend = blendInfo.fDstBlend;
113 fBlendConstant = blendInfo.fBlendConstant;
114
115 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coveragePOI,
116 &firstColorStageIdx, &firstCoverageStageIdx);
117
118 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
egdaniel9cf45bf2014-10-08 06:49:10 -0700119
120 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -0800121 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
122 GrGpu::kStencilPath_DrawType ||
123 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -0800124 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -0700125
bsalomonae59b772014-11-19 08:23:49 -0800126 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800127 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
128 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
129 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800130 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800131 }
egdaniel95131432014-12-09 11:15:43 -0800132
egdanield9aa2182014-10-09 13:47:05 -0700133 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800134 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
135 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
136 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800137 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700138 }
joshualitt79f8fae2014-10-28 17:59:26 -0700139
joshualitt87f48d92014-12-04 10:41:40 -0800140 // let the GP init the batch tracker
141 if (drawState.hasGeometryProcessor()) {
142 GrGeometryProcessor::InitBT init;
143 init.fOutputColor = fDescInfo.fInputColorIsUsed;
144 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed;
145 init.fColor = this->getColor();
146 init.fCoverage = this->getCoverage();
147 fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
148 }
egdaniel95131432014-12-09 11:15:43 -0800149
joshualitt2e3b3e32014-12-09 13:31:14 -0800150 this->setOutputStateInfo(drawState, coverageColor, optFlags, caps);
joshualitt87f48d92014-12-04 10:41:40 -0800151}
egdaniel3658f382014-09-15 07:01:59 -0700152
egdaniel9cf45bf2014-10-08 06:49:10 -0700153void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
joshualitt2e3b3e32014-12-09 13:31:14 -0800154 GrColor coverage,
egdaniel95131432014-12-09 11:15:43 -0800155 GrXferProcessor::OptFlags optFlags,
joshualittdafa4d02014-12-04 08:59:10 -0800156 const GrDrawTargetCaps& caps) {
egdanielc0648242014-09-22 13:17:02 -0700157 // Set this default and then possibly change our mind if there is coverage.
joshualittdafa4d02014-12-04 08:59:10 -0800158 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
159 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700160
bsalomon04ddf892014-11-19 12:36:22 -0800161 // Determine whether we should use dual source blending or shader code to keep coverage
162 // separate from color.
egdaniel95131432014-12-09 11:15:43 -0800163 bool keepCoverageSeparate = !(optFlags & GrXferProcessor::kSetCoverageDrawing_OptFlag);
joshualitt2e3b3e32014-12-09 13:31:14 -0800164 if (keepCoverageSeparate && !ds.hasSolidCoverage(coverage)) {
egdanielc0648242014-09-22 13:17:02 -0700165 if (caps.dualSourceBlendingSupport()) {
166 if (kZero_GrBlendCoeff == fDstBlend) {
167 // write the coverage value to second color
joshualittdafa4d02014-12-04 08:59:10 -0800168 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700169 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
170 } else if (kSA_GrBlendCoeff == fDstBlend) {
171 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800172 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700173 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
174 } else if (kSC_GrBlendCoeff == fDstBlend) {
175 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800176 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700177 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
178 }
joshualittdafa4d02014-12-04 08:59:10 -0800179 } else if (fDescInfo.fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700180 kOne_GrBlendCoeff == fSrcBlend &&
181 kZero_GrBlendCoeff == fDstBlend) {
joshualittdafa4d02014-12-04 08:59:10 -0800182 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700183 }
184 }
egdanielc0648242014-09-22 13:17:02 -0700185}
186
egdaniel95131432014-12-09 11:15:43 -0800187void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
188 GrXferProcessor::OptFlags flags,
189 const GrProcOptInfo& colorPOI,
190 const GrProcOptInfo& coveragePOI,
191 int* firstColorStageIdx,
192 int* firstCoverageStageIdx) {
joshualittdafa4d02014-12-04 08:59:10 -0800193 fDescInfo.fReadsDst = false;
194 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700195
egdaniel95131432014-12-09 11:15:43 -0800196 if (flags & GrXferProcessor::kClearColorStages_OptFlag) {
197 fDescInfo.fInputColorIsUsed = true;
198 *firstColorStageIdx = ds.numColorStages();
199 fDescInfo.fHasVertexColor = false;
200 } else {
201 fDescInfo.fReadsDst = colorPOI.readsDst();
202 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700203 }
egdaniel95131432014-12-09 11:15:43 -0800204
205 if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) {
206 fDescInfo.fInputCoverageIsUsed = true;
207 *firstCoverageStageIdx = ds.numCoverageStages();
208 fDescInfo.fHasVertexCoverage = false;
209 } else {
210 if (coveragePOI.readsDst()) {
211 fDescInfo.fReadsDst = true;
212 }
213 if (coveragePOI.readsFragPosition()) {
214 fDescInfo.fReadsFragPosition = true;
215 }
egdaniela7dc0a82014-09-17 08:25:05 -0700216 }
217}
218
joshualittdafa4d02014-12-04 08:59:10 -0800219void GrOptDrawState::finalize(GrGpu* gpu) {
220 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
221 fFinalized = true;
222}
223
egdaniel89af44a2014-09-26 06:15:04 -0700224////////////////////////////////////////////////////////////////////////////////
225
egdaniel3658f382014-09-15 07:01:59 -0700226bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800227 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800228 return false;
229 }
joshualittdafa4d02014-12-04 08:59:10 -0800230
231 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700232 return false;
233 }
234
235 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800236 this->fFragmentStages.count() != that.fFragmentStages.count() ||
237 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800238 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700239 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
240 this->fSrcBlend != that.fSrcBlend ||
241 this->fDstBlend != that.fDstBlend ||
joshualittdafa4d02014-12-04 08:59:10 -0800242 this->fDrawType != that.fDrawType ||
egdaniel89af44a2014-09-26 06:15:04 -0700243 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800244 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700245 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800246 this->fDrawFace != that.fDrawFace ||
247 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700248 return false;
249 }
250
joshualittdafa4d02014-12-04 08:59:10 -0800251 if (!fDescInfo.fHasVertexCoverage && 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