blob: 93d90b0a2566b4794ccadc06c9cdc07779959845 [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) ||
joshualitt9b989322014-12-15 14:16:27 -080035 GrGpu::kStencilPath_DrawType == drawType));
joshualitt56995b52014-12-11 15:44:02 -080036 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 // Create XferProcessor from DS's XPFactory
44 SkAutoTUnref<GrXferProcessor> xferProcessor(
45 drawState.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
46
joshualitt9b989322014-12-15 14:16:27 -080047 GrColor overrideColor = GrColor_ILLEGAL;
48 if (colorPOI.firstEffectiveStageIndex() != 0) {
49 overrideColor = colorPOI.inputColorToEffectiveStage();
50 }
51
egdaniel95131432014-12-09 11:15:43 -080052 GrXferProcessor::OptFlags optFlags;
53 if (xferProcessor) {
54 fXferProcessor.reset(xferProcessor.get());
55
56 optFlags = xferProcessor->getOptimizations(colorPOI,
57 coveragePOI,
egdaniel95131432014-12-09 11:15:43 -080058 drawState.isColorWriteDisabled(),
59 drawState.getStencil().doesWrite(),
joshualitt9b989322014-12-15 14:16:27 -080060 &overrideColor,
egdanielc2304142014-12-11 13:15:13 -080061 caps);
egdaniel95131432014-12-09 11:15:43 -080062 }
bsalomonb03c4a32014-11-20 09:56:11 -080063
64 // When path rendering the stencil settings are not always set on the draw state
65 // so we must check the draw type. In cases where we will skip drawing we simply return a
66 // null GrOptDrawState.
egdaniel95131432014-12-09 11:15:43 -080067 if (!xferProcessor || ((GrXferProcessor::kSkipDraw_OptFlag & optFlags) &&
68 GrGpu::kStencilPath_DrawType != drawType)) {
bsalomonb03c4a32014-11-20 09:56:11 -080069 // Set the fields that don't default init and return. The lack of a render target will
70 // indicate that this can be skipped.
71 fFlags = 0;
bsalomonb03c4a32014-11-20 09:56:11 -080072 fDrawFace = GrDrawState::kInvalid_DrawFace;
bsalomonb03c4a32014-11-20 09:56:11 -080073 fViewMatrix.reset();
74 return;
75 }
76
77 fRenderTarget.reset(drawState.fRenderTarget.get());
78 SkASSERT(fRenderTarget);
joshualitt54e0c122014-11-19 09:38:51 -080079 fScissorState = scissorState;
egdaniel3658f382014-09-15 07:01:59 -070080 fViewMatrix = drawState.getViewMatrix();
egdaniel3658f382014-09-15 07:01:59 -070081 fStencilSettings = drawState.getStencil();
bsalomon04ddf892014-11-19 12:36:22 -080082 fDrawFace = drawState.getDrawFace();
joshualitt9176e2c2014-11-20 07:28:52 -080083 // TODO move this out of optDrawState
84 if (dstCopy) {
85 fDstCopy = *dstCopy;
86 }
87
bsalomon04ddf892014-11-19 12:36:22 -080088 fFlags = 0;
89 if (drawState.isHWAntialias()) {
90 fFlags |= kHWAA_Flag;
91 }
92 if (drawState.isColorWriteDisabled()) {
93 fFlags |= kDisableColorWrite_Flag;
94 }
95 if (drawState.isDither()) {
96 fFlags |= kDither_Flag;
97 }
98
joshualitt9b989322014-12-15 14:16:27 -080099 // TODO move local coords completely into GP
joshualitt56995b52014-12-11 15:44:02 -0800100 bool hasLocalCoords = gp && gp->hasLocalCoords();
egdaniel9cf45bf2014-10-08 06:49:10 -0700101
egdaniel912b3d22014-11-17 07:45:53 -0800102 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
egdaniel912b3d22014-11-17 07:45:53 -0800103
104 // TODO: Once we can handle single or four channel input into coverage stages then we can use
105 // drawState's coverageProcInfo (like color above) to set this initial information.
106 int firstCoverageStageIdx = 0;
egdaniel912b3d22014-11-17 07:45:53 -0800107
egdaniel95131432014-12-09 11:15:43 -0800108 GrXferProcessor::BlendInfo blendInfo;
109 fXferProcessor->getBlendInfo(&blendInfo);
egdaniel95131432014-12-09 11:15:43 -0800110
111 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coveragePOI,
112 &firstColorStageIdx, &firstCoverageStageIdx);
113
114 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
egdaniel9cf45bf2014-10-08 06:49:10 -0700115
bsalomonae59b772014-11-19 08:23:49 -0800116 // Copy Stages from DS to ODS
bsalomonae59b772014-11-19 08:23:49 -0800117 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
118 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
119 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800120 (drawState.fColorStages[i], hasLocalCoords));
bsalomonae59b772014-11-19 08:23:49 -0800121 }
egdaniel95131432014-12-09 11:15:43 -0800122
egdanield9aa2182014-10-09 13:47:05 -0700123 fNumColorStages = fFragmentStages.count();
bsalomonae59b772014-11-19 08:23:49 -0800124 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) {
125 SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
126 GrPendingFragmentStage,
joshualitt2dd1ae02014-12-03 06:24:10 -0800127 (drawState.fCoverageStages[i], hasLocalCoords));
egdaniel9cf45bf2014-10-08 06:49:10 -0700128 }
joshualitt79f8fae2014-10-28 17:59:26 -0700129
joshualitt87f48d92014-12-04 10:41:40 -0800130 // let the GP init the batch tracker
joshualitt9b989322014-12-15 14:16:27 -0800131 GrGeometryProcessor::InitBT init;
132 init.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag);
133 init.fOverrideColor = init.fColorIgnored ? GrColor_ILLEGAL : overrideColor;
134 init.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag);
135 fPrimitiveProcessor->initBatchTracker(&fBatchTracker, init);
egdanielc0648242014-09-22 13:17:02 -0700136}
137
egdaniel95131432014-12-09 11:15:43 -0800138void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
139 GrXferProcessor::OptFlags flags,
140 const GrProcOptInfo& colorPOI,
141 const GrProcOptInfo& coveragePOI,
142 int* firstColorStageIdx,
143 int* firstCoverageStageIdx) {
joshualittdafa4d02014-12-04 08:59:10 -0800144 fDescInfo.fReadsDst = false;
145 fDescInfo.fReadsFragPosition = false;
egdaniela7dc0a82014-09-17 08:25:05 -0700146
joshualitt9b989322014-12-15 14:16:27 -0800147 if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
148 (flags & GrXferProcessor::kOverrideColor_OptFlag)) {
egdaniel95131432014-12-09 11:15:43 -0800149 *firstColorStageIdx = ds.numColorStages();
egdaniel95131432014-12-09 11:15:43 -0800150 } else {
151 fDescInfo.fReadsDst = colorPOI.readsDst();
152 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
egdaniela7dc0a82014-09-17 08:25:05 -0700153 }
egdaniel95131432014-12-09 11:15:43 -0800154
joshualitt9b989322014-12-15 14:16:27 -0800155 if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
egdaniel95131432014-12-09 11:15:43 -0800156 *firstCoverageStageIdx = ds.numCoverageStages();
egdaniel95131432014-12-09 11:15:43 -0800157 } else {
158 if (coveragePOI.readsDst()) {
159 fDescInfo.fReadsDst = true;
160 }
161 if (coveragePOI.readsFragPosition()) {
162 fDescInfo.fReadsFragPosition = true;
163 }
egdaniela7dc0a82014-09-17 08:25:05 -0700164 }
165}
166
joshualittdafa4d02014-12-04 08:59:10 -0800167void GrOptDrawState::finalize(GrGpu* gpu) {
168 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc);
169 fFinalized = true;
170}
171
egdaniel89af44a2014-09-26 06:15:04 -0700172////////////////////////////////////////////////////////////////////////////////
173
joshualitt9b989322014-12-15 14:16:27 -0800174bool GrOptDrawState::combineIfPossible(const GrOptDrawState& that) {
joshualittdafa4d02014-12-04 08:59:10 -0800175 if (fDescInfo != that.fDescInfo) {
joshualittf78c60c2014-12-04 06:01:45 -0800176 return false;
177 }
joshualittdafa4d02014-12-04 08:59:10 -0800178
egdaniel89af44a2014-09-26 06:15:04 -0700179 if (this->getRenderTarget() != that.getRenderTarget() ||
joshualittdafa4d02014-12-04 08:59:10 -0800180 this->fFragmentStages.count() != that.fFragmentStages.count() ||
181 this->fNumColorStages != that.fNumColorStages ||
joshualitt54e0c122014-11-19 09:38:51 -0800182 this->fScissorState != that.fScissorState ||
egdaniel89af44a2014-09-26 06:15:04 -0700183 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
joshualittdafa4d02014-12-04 08:59:10 -0800184 this->fDrawType != that.fDrawType ||
bsalomon04ddf892014-11-19 12:36:22 -0800185 this->fFlags != that.fFlags ||
egdaniel89af44a2014-09-26 06:15:04 -0700186 this->fStencilSettings != that.fStencilSettings ||
joshualitt9176e2c2014-11-20 07:28:52 -0800187 this->fDrawFace != that.fDrawFace ||
188 this->fDstCopy.texture() != that.fDstCopy.texture()) {
egdaniel89af44a2014-09-26 06:15:04 -0700189 return false;
190 }
191
joshualitt9b989322014-12-15 14:16:27 -0800192 if (!this->getPrimitiveProcessor()->canMakeEqual(fBatchTracker,
193 *that.getPrimitiveProcessor(),
194 that.getBatchTracker())) {
egdaniel89af44a2014-09-26 06:15:04 -0700195 return false;
196 }
197
egdanielc2304142014-12-11 13:15:13 -0800198 if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) {
199 return false;
200 }
201
bsalomonae59b772014-11-19 08:23:49 -0800202 // The program desc comparison should have already assured that the stage counts match.
203 SkASSERT(this->numFragmentStages() == that.numFragmentStages());
egdanield9aa2182014-10-09 13:47:05 -0700204 for (int i = 0; i < this->numFragmentStages(); i++) {
bsalomonae59b772014-11-19 08:23:49 -0800205
206 if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
egdaniel89af44a2014-09-26 06:15:04 -0700207 return false;
208 }
209 }
joshualitt9b989322014-12-15 14:16:27 -0800210
211 // Now update the GrPrimitiveProcessor's batch tracker
212 fPrimitiveProcessor->makeEqual(&fBatchTracker, that.getBatchTracker());
egdaniel89af44a2014-09-26 06:15:04 -0700213 return true;
214}
215