blob: 60360d21c6168d3dd8134c6e3b8eb483bb25a60e [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,
joshualitt56995b52014-12-11 15:44:02 -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
joshualitt56995b52014-12-11 15:44:02 -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();
joshualitt56995b52014-12-11 15:44:02 -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,
egdanielc2304142014-12-11 13:15:13 -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;
bsalomonb03c4a32014-11-20 09:56:11 -080075 fViewMatrix.reset();
76 return;
77 }
78
79 fRenderTarget.reset(drawState.fRenderTarget.get());
80 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080081 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070082 fViewMatrix = drawState.getViewMatrix();
egdaniel3658f382014-09-15 07:01:59 -070083 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080084 fDrawFace = drawState.getDrawFace();
joshualitt9176e2c2014-11-20 07:28:52 -080085 // TODO move this out of optDrawState
86 if (dstCopy) {
87 fDstCopy = *dstCopy;
88 }
89
bsalomon04ddf892014-11-19 12:36:22 -080090 fFlags = 0;
91 if (drawState.isHWAntialias()) {
92 fFlags |= kHWAA_Flag;
93 }
94 if (drawState.isColorWriteDisabled()) {
95 fFlags |= kDisableColorWrite_Flag;
96 }
97 if (drawState.isDither()) {
98 fFlags |= kDither_Flag;
99 }
100
joshualitt56995b52014-12-11 15:44:02 -0800101 fDescInfo.fHasVertexColor = gp && gp->hasVertexColor();
egdaniel3658f382014-09-15 07:01:59 -0700102
joshualitt56995b52014-12-11 15:44:02 -0800103 fDescInfo.fHasVertexCoverage = gp && gp->hasVertexCoverage();
joshualitt2dd1ae02014-12-03 06:24:10 -0800104
joshualitt56995b52014-12-11 15:44:02 -0800105 bool hasLocalCoords = gp && gp->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -0700106
egdaniel912b3d22014-11-17 07:45:53 -0800107 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
joshualittdafa4d02014-12-04 08:59:10 -0800108 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
egdaniel912b3d22014-11-17 07:45:53 -0800109 if (colorPOI.removeVertexAttrib()) {
joshualittdafa4d02014-12-04 08:59:10 -0800110 fDescInfo.fHasVertexColor = false;
egdaniel912b3d22014-11-17 07:45:53 -0800111 }
112
113 // TODO: Once we can handle single or four channel input into coverage stages then we can use
114 // drawState's coverageProcInfo (like color above) to set this initial information.
115 int firstCoverageStageIdx = 0;
joshualittdafa4d02014-12-04 08:59:10 -0800116 fDescInfo.fInputCoverageIsUsed = true;
egdaniel912b3d22014-11-17 07:45:53 -0800117
egdaniel95131432014-12-09 11:15:43 -0800118 GrXferProcessor::BlendInfo blendInfo;
119 fXferProcessor->getBlendInfo(&blendInfo);
egdaniel95131432014-12-09 11:15:43 -0800120
121 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coveragePOI,
122 &firstColorStageIdx, &firstCoverageStageIdx);
123
124 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
egdaniel9cf45bf2014-10-08 06:49:10 -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
joshualitt56995b52014-12-11 15:44:02 -0800141 if (gp) {
joshualitt87f48d92014-12-04 10:41:40 -0800142 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 }
egdanielc0648242014-09-22 13:17:02 -0700149}
150
egdaniel95131432014-12-09 11:15:43 -0800151void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
152 GrXferProcessor::OptFlags flags,
153 const GrProcOptInfo& colorPOI,
154 const GrProcOptInfo& coveragePOI,
155 int* firstColorStageIdx,
156 int* firstCoverageStageIdx) {
joshualittdafa4d02014-12-04 08:59:10 -0800157 fDescInfo.fReadsDst = false;
158 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700159
egdaniel95131432014-12-09 11:15:43 -0800160 if (flags & GrXferProcessor::kClearColorStages_OptFlag) {
161 fDescInfo.fInputColorIsUsed = true;
162 *firstColorStageIdx = ds.numColorStages();
163 fDescInfo.fHasVertexColor = false;
164 } else {
165 fDescInfo.fReadsDst = colorPOI.readsDst();
166 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700167 }
egdaniel95131432014-12-09 11:15:43 -0800168
169 if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) {
170 fDescInfo.fInputCoverageIsUsed = true;
171 *firstCoverageStageIdx = ds.numCoverageStages();
172 fDescInfo.fHasVertexCoverage = false;
173 } else {
174 if (coveragePOI.readsDst()) {
175 fDescInfo.fReadsDst = true;
176 }
177 if (coveragePOI.readsFragPosition()) {
178 fDescInfo.fReadsFragPosition = true;
179 }
egdaniela7dc0a82014-09-17 08:25:05 -0700180 }
181}
182
joshualittdafa4d02014-12-04 08:59:10 -0800183void GrOptDrawState::finalize(GrGpu* gpu) {
184 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
185 fFinalized = true;
186}
187
egdaniel89af44a2014-09-26 06:15:04 -0700188////////////////////////////////////////////////////////////////////////////////
189
egdaniel3658f382014-09-15 07:01:59 -0700190bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
joshualittdafa4d02014-12-04 08:59:10 -0800191 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800192 return false;
193 }
joshualittdafa4d02014-12-04 08:59:10 -0800194
195 if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
egdaniel89af44a2014-09-26 06:15:04 -0700196 return false;
197 }
198
199 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800200 this->fFragmentStages.count() != that.fFragmentStages.count() ||
201 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800202 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700203 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
joshualittdafa4d02014-12-04 08:59:10 -0800204 this->fDrawType != that.fDrawType ||
bsalomon04ddf892014-11-19 12:36:22 -0800205 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700206 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800207 this->fDrawFace != that.fDrawFace ||
208 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700209 return false;
210 }
211
joshualittdafa4d02014-12-04 08:59:10 -0800212 if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
egdaniel89af44a2014-09-26 06:15:04 -0700213 return false;
214 }
215
egdaniel89af44a2014-09-26 06:15:04 -0700216 if (this->hasGeometryProcessor()) {
217 if (!that.hasGeometryProcessor()) {
218 return false;
joshualitta5305a12014-10-10 17:47:00 -0700219 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -0700220 return false;
221 }
222 } else if (that.hasGeometryProcessor()) {
223 return false;
224 }
225
egdanielc2304142014-12-11 13:15:13 -0800226 if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) {
227 return false;
228 }
229
bsalomonae59b772014-11-19 08:23:49 -0800230 // The program desc comparison should have already assured that the stage counts match.
231 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700232 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800233
234 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700235 return false;
236 }
237 }
egdaniel89af44a2014-09-26 06:15:04 -0700238 return true;
239}
240