blob: 010fe4b7392fb2444a8e4ad2c4f4d91f004dee6f [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,
joshualittc6bc58e2014-12-10 13:48:57 -080017 const GrGeometryProcessor* gp,
18 const GrPathProcessor* pathProc,
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) {
24 fDrawType = drawType;
egdaniel95131432014-12-09 11:15:43 -080025
joshualittc6bc58e2014-12-10 13:48:57 -080026 // Copy GeometryProcesssor from DS or ODS
27 if (gp) {
28 SkASSERT(!pathProc);
29 SkASSERT(!(GrGpu::IsPathRenderingDrawType(drawType) ||
30 GrGpu::kStencilPath_DrawType == drawType));
31 fGeometryProcessor.reset(gp);
32 fPrimitiveProcessor.reset(gp);
33 } else {
34 SkASSERT(!gp && pathProc && (GrGpu::IsPathRenderingDrawType(drawType) ||
35 GrGpu::kStencilPath_DrawType == drawType));
36 fPrimitiveProcessor.reset(pathProc);
37 }
38
39
40 const GrProcOptInfo& colorPOI = drawState.colorProcInfo(fPrimitiveProcessor);
41 const GrProcOptInfo& coveragePOI = drawState.coverageProcInfo(fPrimitiveProcessor);
egdaniel95131432014-12-09 11:15:43 -080042
43 fColor = colorPOI.inputColorToEffectiveStage();
joshualittc6bc58e2014-12-10 13:48:57 -080044 // TODO fix this when coverage stages work correctly
45 // fCoverage = coveragePOI.inputColorToEffectiveStage();
46 fCoverage = fPrimitiveProcessor->coverage();
egdaniel95131432014-12-09 11:15:43 -080047
48 // Create XferProcessor from DS's XPFactory
49 SkAutoTUnref<GrXferProcessor> xferProcessor(
50 drawState.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
51
52 GrXferProcessor::OptFlags optFlags;
53 if (xferProcessor) {
54 fXferProcessor.reset(xferProcessor.get());
55
56 optFlags = xferProcessor->getOptimizations(colorPOI,
57 coveragePOI,
58 drawState.isCoverageDrawing(),
59 drawState.isColorWriteDisabled(),
60 drawState.getStencil().doesWrite(),
61 &fColor,
egdaniel4dffc942014-12-10 07:43:49 -080062 &fCoverage,
63 caps);
egdaniel95131432014-12-09 11:15:43 -080064 }
bsalomonb03c4a32014-11-20 09:56:11 -080065
66 // When path rendering the stencil settings are not always set on the draw state
67 // so we must check the draw type. In cases where we will skip drawing we simply return a
68 // null GrOptDrawState.
egdaniel95131432014-12-09 11:15:43 -080069 if (!xferProcessor || ((GrXferProcessor::kSkipDraw_OptFlag & optFlags) &&
70 GrGpu::kStencilPath_DrawType != drawType)) {
bsalomonb03c4a32014-11-20 09:56:11 -080071 // Set the fields that don't default init and return. The lack of a render target will
72 // indicate that this can be skipped.
73 fFlags = 0;
bsalomonb03c4a32014-11-20 09:56:11 -080074 fDrawFace = GrDrawState::kInvalid_DrawFace;
75 fSrcBlend = kZero_GrBlendCoeff;
76 fDstBlend = kZero_GrBlendCoeff;
77 fBlendConstant = 0x0;
78 fViewMatrix.reset();
79 return;
80 }
81
82 fRenderTarget.reset(drawState.fRenderTarget.get());
83 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080084 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070085 fViewMatrix = drawState.getViewMatrix();
egdaniel3658f382014-09-15 07:01:59 -070086 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080087 fDrawFace = drawState.getDrawFace();
joshualitt9176e2c2014-11-20 07:28:52 -080088 // TODO move this out of optDrawState
89 if (dstCopy) {
90 fDstCopy = *dstCopy;
91 }
92
bsalomon04ddf892014-11-19 12:36:22 -080093 fFlags = 0;
94 if (drawState.isHWAntialias()) {
95 fFlags |= kHWAA_Flag;
96 }
97 if (drawState.isColorWriteDisabled()) {
98 fFlags |= kDisableColorWrite_Flag;
99 }
100 if (drawState.isDither()) {
101 fFlags |= kDither_Flag;
102 }
103
joshualittc6bc58e2014-12-10 13:48:57 -0800104 fDescInfo.fHasVertexColor = gp && gp->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -0700105
joshualittc6bc58e2014-12-10 13:48:57 -0800106 fDescInfo.fHasVertexCoverage = gp && gp->hasVertexCoverage();
joshualitt2dd1ae02014-12-03 06:24:10 -0800107
joshualittc6bc58e2014-12-10 13:48:57 -0800108 bool hasLocalCoords = gp && gp->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -0700109
egdaniel912b3d22014-11-17 07:45:53 -0800110 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
joshualittdafa4d02014-12-04 08:59:10 -0800111 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
egdaniel912b3d22014-11-17 07:45:53 -0800112 if (colorPOI.removeVertexAttrib()) {
joshualittdafa4d02014-12-04 08:59:10 -0800113 fDescInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -0800114 }
115
116 // TODO: Once we can handle single or four channel input into coverage stages then we can use
117 // drawState's coverageProcInfo (like color above) to set this initial information.
118 int firstCoverageStageIdx = 0;
joshualittdafa4d02014-12-04 08:59:10 -0800119 fDescInfo.fInputCoverageIsUsed = true;
egdaniel912b3d22014-11-17 07:45:53 -0800120
egdaniel95131432014-12-09 11:15:43 -0800121 GrXferProcessor::BlendInfo blendInfo;
122 fXferProcessor->getBlendInfo(&blendInfo);
123 fSrcBlend = blendInfo.fSrcBlend;
124 fDstBlend = blendInfo.fDstBlend;
125 fBlendConstant = blendInfo.fBlendConstant;
126
127 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coveragePOI,
128 &firstColorStageIdx, &firstCoverageStageIdx);
129
130 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
egdaniel9cf45bf2014-10-08 06:49:10 -0700131
bsalomonae59b772014-11-19 08:23:49 -0800132 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800133 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
134 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
135 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800136 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800137 }
egdaniel95131432014-12-09 11:15:43 -0800138
egdanield9aa2182014-10-09 13:47:05 -0700139 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800140 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
141 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
142 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800143 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700144 }
joshualitt79f8fae2014-10-28 17:59:26 -0700145
joshualitt87f48d92014-12-04 10:41:40 -0800146 // let the GP init the batch tracker
joshualittc6bc58e2014-12-10 13:48:57 -0800147 if (gp) {
joshualitt87f48d92014-12-04 10:41:40 -0800148 GrGeometryProcessor::InitBT init;
149 init.fOutputColor = fDescInfo.fInputColorIsUsed;
150 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed;
151 init.fColor = this->getColor();
152 init.fCoverage = this->getCoverage();
153 fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
154 }
egdanielc0648242014-09-22 13:17:02 -0700155}
156
egdaniel95131432014-12-09 11:15:43 -0800157void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
158 GrXferProcessor::OptFlags flags,
159 const GrProcOptInfo& colorPOI,
160 const GrProcOptInfo& coveragePOI,
161 int* firstColorStageIdx,
162 int* firstCoverageStageIdx) {
joshualittdafa4d02014-12-04 08:59:10 -0800163 fDescInfo.fReadsDst = false;
164 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700165
egdaniel95131432014-12-09 11:15:43 -0800166 if (flags & GrXferProcessor::kClearColorStages_OptFlag) {
167 fDescInfo.fInputColorIsUsed = true;
168 *firstColorStageIdx = ds.numColorStages();
169 fDescInfo.fHasVertexColor = false;
170 } else {
171 fDescInfo.fReadsDst = colorPOI.readsDst();
172 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700173 }
egdaniel95131432014-12-09 11:15:43 -0800174
175 if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) {
176 fDescInfo.fInputCoverageIsUsed = true;
177 *firstCoverageStageIdx = ds.numCoverageStages();
178 fDescInfo.fHasVertexCoverage = false;
179 } else {
180 if (coveragePOI.readsDst()) {
181 fDescInfo.fReadsDst = true;
182 }
183 if (coveragePOI.readsFragPosition()) {
184 fDescInfo.fReadsFragPosition = true;
185 }
egdaniela7dc0a82014-09-17 08:25:05 -0700186 }
187}
188
joshualittdafa4d02014-12-04 08:59:10 -0800189void GrOptDrawState::finalize(GrGpu* gpu) {
190 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
191 fFinalized = true;
192}
193
egdaniel89af44a2014-09-26 06:15:04 -0700194////////////////////////////////////////////////////////////////////////////////
195
egdaniel3658f382014-09-15 07:01:59 -0700196bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800197 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800198 return false;
199 }
joshualittdafa4d02014-12-04 08:59:10 -0800200
201 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700202 return false;
203 }
204
205 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800206 this->fFragmentStages.count() != that.fFragmentStages.count() ||
207 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800208 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700209 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
210 this->fSrcBlend != that.fSrcBlend ||
211 this->fDstBlend != that.fDstBlend ||
joshualittdafa4d02014-12-04 08:59:10 -0800212 this->fDrawType != that.fDrawType ||
egdaniel89af44a2014-09-26 06:15:04 -0700213 this->fBlendConstant != that.fBlendConstant ||
bsalomon04ddf892014-11-19 12:36:22 -0800214 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700215 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800216 this->fDrawFace != that.fDrawFace ||
217 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700218 return false;
219 }
220
joshualittdafa4d02014-12-04 08:59:10 -0800221 if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700222 return false;
223 }
224
egdaniel89af44a2014-09-26 06:15:04 -0700225 if (this->hasGeometryProcessor()) {
226 if (!that.hasGeometryProcessor()) {
227 return false;
joshualitta5305a12014-10-10 17:47:00 -0700228 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700229 return false;
230 }
231 } else if (that.hasGeometryProcessor()) {
232 return false;
233 }
234
egdaniel4dffc942014-12-10 07:43:49 -0800235 if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) {
236 return false;
237 }
238
bsalomonae59b772014-11-19 08:23:49 -0800239 // The program desc comparison should have already assured that the stage counts match.
240 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700241 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800242
243 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700244 return false;
245 }
246 }
egdaniel89af44a2014-09-26 06:15:04 -0700247 return true;
248}
249