blob: d3172010eddce5ea102594dc208fd8a900d829d5 [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,
joshualittdafa4d02014-12-04 08:59:10 -080017 const GrDrawTargetCaps& caps,
joshualitt54e0c122014-11-19 09:38:51 -080018 const ScissorState& scissorState,
joshualitt79f8fae2014-10-28 17:59:26 -070019 const GrDeviceCoordTexture* dstCopy,
joshualittdafa4d02014-12-04 08:59:10 -080020 GrGpu::DrawType drawType)
21 : fFinalized(false) {
22 fDrawType = drawType;
egdaniel95131432014-12-09 11:15:43 -080023
24 const GrProcOptInfo& colorPOI = drawState.colorProcInfo();
25 const GrProcOptInfo& coveragePOI = drawState.coverageProcInfo();
26
27 fColor = colorPOI.inputColorToEffectiveStage();
28 fCoverage = drawState.getCoverage();
29
30 // Create XferProcessor from DS's XPFactory
31 SkAutoTUnref<GrXferProcessor> xferProcessor(
32 drawState.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
33
34 GrXferProcessor::OptFlags optFlags;
35 if (xferProcessor) {
36 fXferProcessor.reset(xferProcessor.get());
37
38 optFlags = xferProcessor->getOptimizations(colorPOI,
39 coveragePOI,
40 drawState.isCoverageDrawing(),
41 drawState.isColorWriteDisabled(),
42 drawState.getStencil().doesWrite(),
43 &fColor,
44 &fCoverage);
45 }
bsalomonb03c4a32014-11-20 09:56:11 -080046
47 // When path rendering the stencil settings are not always set on the draw state
48 // so we must check the draw type. In cases where we will skip drawing we simply return a
49 // null GrOptDrawState.
egdaniel95131432014-12-09 11:15:43 -080050 if (!xferProcessor || ((GrXferProcessor::kSkipDraw_OptFlag & optFlags) &&
51 GrGpu::kStencilPath_DrawType != drawType)) {
bsalomonb03c4a32014-11-20 09:56:11 -080052 // Set the fields that don't default init and return. The lack of a render target will
53 // indicate that this can be skipped.
54 fFlags = 0;
bsalomonb03c4a32014-11-20 09:56:11 -080055 fDrawFace = GrDrawState::kInvalid_DrawFace;
56 fSrcBlend = kZero_GrBlendCoeff;
57 fDstBlend = kZero_GrBlendCoeff;
58 fBlendConstant = 0x0;
59 fViewMatrix.reset();
60 return;
61 }
62
63 fRenderTarget.reset(drawState.fRenderTarget.get());
64 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080065 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070066 fViewMatrix = drawState.getViewMatrix();
egdaniel3658f382014-09-15 07:01:59 -070067 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080068 fDrawFace = drawState.getDrawFace();
joshualitt9176e2c2014-11-20 07:28:52 -080069 // TODO move this out of optDrawState
70 if (dstCopy) {
71 fDstCopy = *dstCopy;
72 }
73
bsalomon04ddf892014-11-19 12:36:22 -080074 fFlags = 0;
75 if (drawState.isHWAntialias()) {
76 fFlags |= kHWAA_Flag;
77 }
78 if (drawState.isColorWriteDisabled()) {
79 fFlags |= kDisableColorWrite_Flag;
80 }
81 if (drawState.isDither()) {
82 fFlags |= kDither_Flag;
83 }
84
joshualittdafa4d02014-12-04 08:59:10 -080085 fDescInfo.fHasVertexColor = drawState.hasGeometryProcessor() &&
86 drawState.getGeometryProcessor()->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -070087
joshualittdafa4d02014-12-04 08:59:10 -080088 fDescInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() &&
89 drawState.getGeometryProcessor()->hasVertexCoverage();
joshualitt2dd1ae02014-12-03 06:24:10 -080090
91 bool hasLocalCoords = drawState.hasGeometryProcessor() &&
92 drawState.getGeometryProcessor()->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -070093
egdaniel912b3d22014-11-17 07:45:53 -080094 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
joshualittdafa4d02014-12-04 08:59:10 -080095 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
egdaniel912b3d22014-11-17 07:45:53 -080096 if (colorPOI.removeVertexAttrib()) {
joshualittdafa4d02014-12-04 08:59:10 -080097 fDescInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -080098 }
99
100 // TODO: Once we can handle single or four channel input into coverage stages then we can use
101 // drawState's coverageProcInfo (like color above) to set this initial information.
102 int firstCoverageStageIdx = 0;
joshualittdafa4d02014-12-04 08:59:10 -0800103 fDescInfo.fInputCoverageIsUsed = true;
egdaniel912b3d22014-11-17 07:45:53 -0800104
joshualitt2dd1ae02014-12-03 06:24:10 -0800105
egdaniel95131432014-12-09 11:15:43 -0800106 GrXferProcessor::BlendInfo blendInfo;
107 fXferProcessor->getBlendInfo(&blendInfo);
108 fSrcBlend = blendInfo.fSrcBlend;
109 fDstBlend = blendInfo.fDstBlend;
110 fBlendConstant = blendInfo.fBlendConstant;
111
112 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coveragePOI,
113 &firstColorStageIdx, &firstCoverageStageIdx);
114
115 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
egdaniel9cf45bf2014-10-08 06:49:10 -0700116
117 // Copy GeometryProcesssor from DS or ODS
joshualitt5478d422014-11-14 16:00:38 -0800118 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) ||
119 GrGpu::kStencilPath_DrawType ||
120 drawState.hasGeometryProcessor());
bsalomonae59b772014-11-19 08:23:49 -0800121 fGeometryProcessor.reset(drawState.getGeometryProcessor());
egdaniel3658f382014-09-15 07:01:59 -0700122
bsalomonae59b772014-11-19 08:23:49 -0800123 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800124 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
125 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
126 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800127 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800128 }
egdaniel95131432014-12-09 11:15:43 -0800129
egdanield9aa2182014-10-09 13:47:05 -0700130 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800131 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
132 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
133 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800134 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700135 }
joshualitt79f8fae2014-10-28 17:59:26 -0700136
joshualitt87f48d92014-12-04 10:41:40 -0800137 // let the GP init the batch tracker
138 if (drawState.hasGeometryProcessor()) {
139 GrGeometryProcessor::InitBT init;
140 init.fOutputColor = fDescInfo.fInputColorIsUsed;
141 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed;
142 init.fColor = this->getColor();
143 init.fCoverage = this->getCoverage();
144 fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
145 }
egdaniel95131432014-12-09 11:15:43 -0800146
147 this->setOutputStateInfo(drawState, optFlags, caps);
joshualitt87f48d92014-12-04 10:41:40 -0800148}
egdaniel3658f382014-09-15 07:01:59 -0700149
egdaniel9cf45bf2014-10-08 06:49:10 -0700150void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
egdaniel95131432014-12-09 11:15:43 -0800151 GrXferProcessor::OptFlags optFlags,
joshualittdafa4d02014-12-04 08:59:10 -0800152 const GrDrawTargetCaps& caps) {
egdanielc0648242014-09-22 13:17:02 -0700153 // Set this default and then possibly change our mind if there is coverage.
joshualittdafa4d02014-12-04 08:59:10 -0800154 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
155 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700156
bsalomon04ddf892014-11-19 12:36:22 -0800157 // Determine whether we should use dual source blending or shader code to keep coverage
158 // separate from color.
egdaniel95131432014-12-09 11:15:43 -0800159 bool keepCoverageSeparate = !(optFlags & GrXferProcessor::kSetCoverageDrawing_OptFlag);
bsalomon04ddf892014-11-19 12:36:22 -0800160 if (keepCoverageSeparate && !ds.hasSolidCoverage()) {
egdanielc0648242014-09-22 13:17:02 -0700161 if (caps.dualSourceBlendingSupport()) {
162 if (kZero_GrBlendCoeff == fDstBlend) {
163 // write the coverage value to second color
joshualittdafa4d02014-12-04 08:59:10 -0800164 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700165 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
166 } else if (kSA_GrBlendCoeff == fDstBlend) {
167 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
joshualittdafa4d02014-12-04 08:59:10 -0800168 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700169 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
170 } else if (kSC_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::kCoverageISC_SecondaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700173 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
174 }
joshualittdafa4d02014-12-04 08:59:10 -0800175 } else if (fDescInfo.fReadsDst &&
egdanielc0648242014-09-22 13:17:02 -0700176 kOne_GrBlendCoeff == fSrcBlend &&
177 kZero_GrBlendCoeff == fDstBlend) {
joshualittdafa4d02014-12-04 08:59:10 -0800178 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
egdanielc0648242014-09-22 13:17:02 -0700179 }
180 }
egdanielc0648242014-09-22 13:17:02 -0700181}
182
egdaniel95131432014-12-09 11:15:43 -0800183void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
184 GrXferProcessor::OptFlags flags,
185 const GrProcOptInfo& colorPOI,
186 const GrProcOptInfo& coveragePOI,
187 int* firstColorStageIdx,
188 int* firstCoverageStageIdx) {
joshualittdafa4d02014-12-04 08:59:10 -0800189 fDescInfo.fReadsDst = false;
190 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700191
egdaniel95131432014-12-09 11:15:43 -0800192 if (flags & GrXferProcessor::kClearColorStages_OptFlag) {
193 fDescInfo.fInputColorIsUsed = true;
194 *firstColorStageIdx = ds.numColorStages();
195 fDescInfo.fHasVertexColor = false;
196 } else {
197 fDescInfo.fReadsDst = colorPOI.readsDst();
198 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700199 }
egdaniel95131432014-12-09 11:15:43 -0800200
201 if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) {
202 fDescInfo.fInputCoverageIsUsed = true;
203 *firstCoverageStageIdx = ds.numCoverageStages();
204 fDescInfo.fHasVertexCoverage = false;
205 } else {
206 if (coveragePOI.readsDst()) {
207 fDescInfo.fReadsDst = true;
208 }
209 if (coveragePOI.readsFragPosition()) {
210 fDescInfo.fReadsFragPosition = true;
211 }
egdaniela7dc0a82014-09-17 08:25:05 -0700212 }
213}
214
joshualittdafa4d02014-12-04 08:59:10 -0800215void GrOptDrawState::finalize(GrGpu* gpu) {
216 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
217 fFinalized = true;
218}
219
egdaniel89af44a2014-09-26 06:15:04 -0700220////////////////////////////////////////////////////////////////////////////////
221
egdaniel3658f382014-09-15 07:01:59 -0700222bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800223 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800224 return false;
225 }
joshualittdafa4d02014-12-04 08:59:10 -0800226
227 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700228 return false;
229 }
230
231 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800232 this->fFragmentStages.count() != that.fFragmentStages.count() ||
233 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800234 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700235 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
236 this->fSrcBlend != that.fSrcBlend ||
237 this->fDstBlend != that.fDstBlend ||
joshualittdafa4d02014-12-04 08:59:10 -0800238 this->fDrawType != that.fDrawType ||
egdaniel89af44a2014-09-26 06:15:04 -0700239 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800240 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700241 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800242 this->fDrawFace != that.fDrawFace ||
243 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700244 return false;
245 }
246
joshualittdafa4d02014-12-04 08:59:10 -0800247 if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700248 return false;
249 }
250
egdaniel89af44a2014-09-26 06:15:04 -0700251 if (this->hasGeometryProcessor()) {
252 if (!that.hasGeometryProcessor()) {
253 return false;
joshualitta5305a12014-10-10 17:47:00 -0700254 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700255 return false;
256 }
257 } else if (that.hasGeometryProcessor()) {
258 return false;
259 }
260
bsalomonae59b772014-11-19 08:23:49 -0800261 // The program desc comparison should have already assured that the stage counts match.
262 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700263 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800264
265 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700266 return false;
267 }
268 }
egdaniel89af44a2014-09-26 06:15:04 -0700269 return true;
270}
271