OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrOptDrawState.h" | 8 #include "GrOptDrawState.h" |
9 | 9 |
10 #include "GrDrawState.h" | 10 #include "GrDrawState.h" |
11 #include "GrDrawTargetCaps.h" | 11 #include "GrDrawTargetCaps.h" |
12 #include "GrGpu.h" | 12 #include "GrGpu.h" |
13 #include "GrProcOptInfo.h" | 13 #include "GrProcOptInfo.h" |
14 #include "GrXferProcessor.h" | |
15 | 14 |
16 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, | 15 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, |
17 const GrDrawTargetCaps& caps, | 16 const GrDrawTargetCaps& caps, |
18 const ScissorState& scissorState, | 17 const ScissorState& scissorState, |
19 const GrDeviceCoordTexture* dstCopy, | 18 const GrDeviceCoordTexture* dstCopy, |
20 GrGpu::DrawType drawType) | 19 GrGpu::DrawType drawType) |
21 : fFinalized(false) { | 20 : fFinalized(false) { |
22 fDrawType = drawType; | 21 fDrawType = drawType; |
23 | 22 GrBlendCoeff optSrcCoeff; |
24 const GrProcOptInfo& colorPOI = drawState.colorProcInfo(); | 23 GrBlendCoeff optDstCoeff; |
25 const GrProcOptInfo& coveragePOI = drawState.coverageProcInfo(); | 24 GrDrawState::BlendOpt blendOpt = drawState.getBlendOpt(false, &optSrcCoeff,
&optDstCoeff); |
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.isColorWriteDisable
d(), | |
42 drawState.getStencil().doesWr
ite(), | |
43 &fColor, | |
44 &fCoverage); | |
45 } | |
46 | 25 |
47 // When path rendering the stencil settings are not always set on the draw s
tate | 26 // When path rendering the stencil settings are not always set on the draw s
tate |
48 // so we must check the draw type. In cases where we will skip drawing we si
mply return a | 27 // so we must check the draw type. In cases where we will skip drawing we si
mply return a |
49 // null GrOptDrawState. | 28 // null GrOptDrawState. |
50 if (!xferProcessor || ((GrXferProcessor::kSkipDraw_OptFlag & optFlags) && | 29 if (GrDrawState::kSkipDraw_BlendOpt == blendOpt && GrGpu::kStencilPath_DrawT
ype != drawType) { |
51 GrGpu::kStencilPath_DrawType != drawType)) { | |
52 // Set the fields that don't default init and return. The lack of a rend
er target will | 30 // Set the fields that don't default init and return. The lack of a rend
er target will |
53 // indicate that this can be skipped. | 31 // indicate that this can be skipped. |
54 fFlags = 0; | 32 fFlags = 0; |
55 fDrawFace = GrDrawState::kInvalid_DrawFace; | 33 fDrawFace = GrDrawState::kInvalid_DrawFace; |
56 fSrcBlend = kZero_GrBlendCoeff; | 34 fSrcBlend = kZero_GrBlendCoeff; |
57 fDstBlend = kZero_GrBlendCoeff; | 35 fDstBlend = kZero_GrBlendCoeff; |
58 fBlendConstant = 0x0; | 36 fBlendConstant = 0x0; |
59 fViewMatrix.reset(); | 37 fViewMatrix.reset(); |
60 return; | 38 return; |
61 } | 39 } |
62 | 40 |
63 fRenderTarget.reset(drawState.fRenderTarget.get()); | 41 fRenderTarget.reset(drawState.fRenderTarget.get()); |
64 SkASSERT(fRenderTarget); | 42 SkASSERT(fRenderTarget); |
65 fScissorState = scissorState; | 43 fScissorState = scissorState; |
66 fViewMatrix = drawState.getViewMatrix(); | 44 fViewMatrix = drawState.getViewMatrix(); |
| 45 fBlendConstant = drawState.getBlendConstant(); |
67 fStencilSettings = drawState.getStencil(); | 46 fStencilSettings = drawState.getStencil(); |
68 fDrawFace = drawState.getDrawFace(); | 47 fDrawFace = drawState.getDrawFace(); |
| 48 fSrcBlend = optSrcCoeff; |
| 49 fDstBlend = optDstCoeff; |
| 50 |
69 // TODO move this out of optDrawState | 51 // TODO move this out of optDrawState |
70 if (dstCopy) { | 52 if (dstCopy) { |
71 fDstCopy = *dstCopy; | 53 fDstCopy = *dstCopy; |
72 } | 54 } |
73 | 55 |
74 fFlags = 0; | 56 fFlags = 0; |
75 if (drawState.isHWAntialias()) { | 57 if (drawState.isHWAntialias()) { |
76 fFlags |= kHWAA_Flag; | 58 fFlags |= kHWAA_Flag; |
77 } | 59 } |
78 if (drawState.isColorWriteDisabled()) { | 60 if (drawState.isColorWriteDisabled()) { |
79 fFlags |= kDisableColorWrite_Flag; | 61 fFlags |= kDisableColorWrite_Flag; |
80 } | 62 } |
81 if (drawState.isDither()) { | 63 if (drawState.isDither()) { |
82 fFlags |= kDither_Flag; | 64 fFlags |= kDither_Flag; |
83 } | 65 } |
84 | 66 |
85 fDescInfo.fHasVertexColor = drawState.hasGeometryProcessor() && | 67 fDescInfo.fHasVertexColor = drawState.hasGeometryProcessor() && |
86 drawState.getGeometryProcessor()->hasVertexColor
(); | 68 drawState.getGeometryProcessor()->hasVertexColor
(); |
87 | 69 |
88 fDescInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() && | 70 fDescInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() && |
89 drawState.getGeometryProcessor()->hasVertexCo
verage(); | 71 drawState.getGeometryProcessor()->hasVertexCo
verage(); |
90 | 72 |
91 bool hasLocalCoords = drawState.hasGeometryProcessor() && | 73 bool hasLocalCoords = drawState.hasGeometryProcessor() && |
92 drawState.getGeometryProcessor()->hasLocalCoords(); | 74 drawState.getGeometryProcessor()->hasLocalCoords(); |
93 | 75 |
| 76 const GrProcOptInfo& colorPOI = drawState.colorProcInfo(); |
94 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex(); | 77 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex(); |
95 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed(); | 78 fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed(); |
| 79 fColor = colorPOI.inputColorToEffectiveStage(); |
96 if (colorPOI.removeVertexAttrib()) { | 80 if (colorPOI.removeVertexAttrib()) { |
97 fDescInfo.fHasVertexColor = false; | 81 fDescInfo.fHasVertexColor = false; |
98 } | 82 } |
99 | 83 |
100 // TODO: Once we can handle single or four channel input into coverage stage
s then we can use | 84 // TODO: Once we can handle single or four channel input into coverage stage
s then we can use |
101 // drawState's coverageProcInfo (like color above) to set this initial infor
mation. | 85 // drawState's coverageProcInfo (like color above) to set this initial infor
mation. |
102 int firstCoverageStageIdx = 0; | 86 int firstCoverageStageIdx = 0; |
103 fDescInfo.fInputCoverageIsUsed = true; | 87 fDescInfo.fInputCoverageIsUsed = true; |
| 88 fCoverage = drawState.getCoverage(); |
104 | 89 |
| 90 this->adjustProgramForBlendOpt(drawState, blendOpt, &firstColorStageIdx, |
| 91 &firstCoverageStageIdx); |
105 | 92 |
106 GrXferProcessor::BlendInfo blendInfo; | 93 this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, ha
sLocalCoords); |
107 fXferProcessor->getBlendInfo(&blendInfo); | |
108 fSrcBlend = blendInfo.fSrcBlend; | |
109 fDstBlend = blendInfo.fDstBlend; | |
110 fBlendConstant = blendInfo.fBlendConstant; | |
111 | |
112 this->adjustProgramFromOptimizations(drawState, optFlags, colorPOI, coverage
POI, | |
113 &firstColorStageIdx, &firstCoverageStag
eIdx); | |
114 | |
115 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords; | |
116 | 94 |
117 // Copy GeometryProcesssor from DS or ODS | 95 // Copy GeometryProcesssor from DS or ODS |
118 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) || | 96 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) || |
119 GrGpu::kStencilPath_DrawType || | 97 GrGpu::kStencilPath_DrawType || |
120 drawState.hasGeometryProcessor()); | 98 drawState.hasGeometryProcessor()); |
121 fGeometryProcessor.reset(drawState.getGeometryProcessor()); | 99 fGeometryProcessor.reset(drawState.getGeometryProcessor()); |
122 | 100 |
| 101 // Create XferProcessor from DS's XPFactory |
| 102 const GrXferProcessor* xpProcessor = drawState.getXPFactory()->createXferPro
cessor(); |
| 103 fXferProcessor.reset(xpProcessor); |
| 104 xpProcessor->unref(); |
| 105 |
123 // Copy Stages from DS to ODS | 106 // Copy Stages from DS to ODS |
124 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) { | 107 for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) { |
125 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, | 108 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, |
126 GrPendingFragmentStage, | 109 GrPendingFragmentStage, |
127 (drawState.fColorStages[i], hasLocalCoords)); | 110 (drawState.fColorStages[i], hasLocalCoords)); |
128 } | 111 } |
129 | |
130 fNumColorStages = fFragmentStages.count(); | 112 fNumColorStages = fFragmentStages.count(); |
131 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i)
{ | 113 for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i)
{ |
132 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, | 114 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, |
133 GrPendingFragmentStage, | 115 GrPendingFragmentStage, |
134 (drawState.fCoverageStages[i], hasLocalCoords)); | 116 (drawState.fCoverageStages[i], hasLocalCoords)); |
135 } | 117 } |
136 | 118 |
| 119 this->setOutputStateInfo(drawState, blendOpt, caps); |
| 120 |
137 // let the GP init the batch tracker | 121 // let the GP init the batch tracker |
138 if (drawState.hasGeometryProcessor()) { | 122 if (drawState.hasGeometryProcessor()) { |
139 GrGeometryProcessor::InitBT init; | 123 GrGeometryProcessor::InitBT init; |
140 init.fOutputColor = fDescInfo.fInputColorIsUsed; | 124 init.fOutputColor = fDescInfo.fInputColorIsUsed; |
141 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed; | 125 init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed; |
142 init.fColor = this->getColor(); | 126 init.fColor = this->getColor(); |
143 init.fCoverage = this->getCoverage(); | 127 init.fCoverage = this->getCoverage(); |
144 fGeometryProcessor->initBatchTracker(&fBatchTracker, init); | 128 fGeometryProcessor->initBatchTracker(&fBatchTracker, init); |
145 } | 129 } |
146 | |
147 this->setOutputStateInfo(drawState, optFlags, caps); | |
148 } | 130 } |
149 | 131 |
150 void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds, | 132 void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds, |
151 GrXferProcessor::OptFlags optFlags, | 133 GrDrawState::BlendOpt blendOpt, |
152 const GrDrawTargetCaps& caps) { | 134 const GrDrawTargetCaps& caps) { |
153 // Set this default and then possibly change our mind if there is coverage. | 135 // Set this default and then possibly change our mind if there is coverage. |
154 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType; | 136 fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType; |
155 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType; | 137 fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType; |
156 | 138 |
157 // Determine whether we should use dual source blending or shader code to ke
ep coverage | 139 // Determine whether we should use dual source blending or shader code to ke
ep coverage |
158 // separate from color. | 140 // separate from color. |
159 bool keepCoverageSeparate = !(optFlags & GrXferProcessor::kSetCoverageDrawin
g_OptFlag); | 141 bool keepCoverageSeparate = !(GrDrawState::kCoverageAsAlpha_BlendOpt == blen
dOpt || |
| 142 GrDrawState::kEmitCoverage_BlendOpt == blendOp
t); |
160 if (keepCoverageSeparate && !ds.hasSolidCoverage()) { | 143 if (keepCoverageSeparate && !ds.hasSolidCoverage()) { |
161 if (caps.dualSourceBlendingSupport()) { | 144 if (caps.dualSourceBlendingSupport()) { |
162 if (kZero_GrBlendCoeff == fDstBlend) { | 145 if (kZero_GrBlendCoeff == fDstBlend) { |
163 // write the coverage value to second color | 146 // write the coverage value to second color |
164 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_Second
aryOutputType; | 147 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_Second
aryOutputType; |
165 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; | 148 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
166 } else if (kSA_GrBlendCoeff == fDstBlend) { | 149 } else if (kSA_GrBlendCoeff == fDstBlend) { |
167 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
covered. | 150 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
covered. |
168 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_Sec
ondaryOutputType; | 151 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_Sec
ondaryOutputType; |
169 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; | 152 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
170 } else if (kSC_GrBlendCoeff == fDstBlend) { | 153 } else if (kSC_GrBlendCoeff == fDstBlend) { |
171 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
covered. | 154 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
covered. |
172 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_Sec
ondaryOutputType; | 155 fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_Sec
ondaryOutputType; |
173 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; | 156 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
174 } | 157 } |
175 } else if (fDescInfo.fReadsDst && | 158 } else if (fDescInfo.fReadsDst && |
176 kOne_GrBlendCoeff == fSrcBlend && | 159 kOne_GrBlendCoeff == fSrcBlend && |
177 kZero_GrBlendCoeff == fDstBlend) { | 160 kZero_GrBlendCoeff == fDstBlend) { |
178 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_Primar
yOutputType; | 161 fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_Primar
yOutputType; |
179 } | 162 } |
180 } | 163 } |
181 } | 164 } |
182 | 165 |
183 void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds, | 166 void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds, |
184 GrXferProcessor::OptFlags fl
ags, | 167 GrDrawState::BlendOpt blendOpt, |
185 const GrProcOptInfo& colorPO
I, | 168 int* firstColorStageIdx, |
186 const GrProcOptInfo& coverag
ePOI, | 169 int* firstCoverageStageIdx) { |
187 int* firstColorStageIdx, | 170 switch (blendOpt) { |
188 int* firstCoverageStageIdx)
{ | 171 case GrDrawState::kNone_BlendOpt: |
| 172 case GrDrawState::kSkipDraw_BlendOpt: |
| 173 case GrDrawState::kCoverageAsAlpha_BlendOpt: |
| 174 break; |
| 175 case GrDrawState::kEmitCoverage_BlendOpt: |
| 176 fColor = 0xffffffff; |
| 177 fDescInfo.fInputColorIsUsed = true; |
| 178 *firstColorStageIdx = ds.numColorStages(); |
| 179 fDescInfo.fHasVertexColor = false; |
| 180 break; |
| 181 case GrDrawState::kEmitTransBlack_BlendOpt: |
| 182 fColor = 0; |
| 183 fCoverage = 0xff; |
| 184 fDescInfo.fInputColorIsUsed = true; |
| 185 fDescInfo.fInputCoverageIsUsed = true; |
| 186 *firstColorStageIdx = ds.numColorStages(); |
| 187 *firstCoverageStageIdx = ds.numCoverageStages(); |
| 188 fDescInfo.fHasVertexColor = false; |
| 189 fDescInfo.fHasVertexCoverage = false; |
| 190 break; |
| 191 } |
| 192 } |
| 193 |
| 194 static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool*
readsFragPosition) { |
| 195 if (stage.getProcessor()->willReadDstColor()) { |
| 196 *readsDst = true; |
| 197 } |
| 198 if (stage.getProcessor()->willReadFragmentPosition()) { |
| 199 *readsFragPosition = true; |
| 200 } |
| 201 } |
| 202 |
| 203 void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx
, |
| 204 int firstCoverageStageIdx, bool hasLocalCoord
s) { |
| 205 // We will need a local coord attrib if there is one currently set on the op
tState and we are |
| 206 // actually generating some effect code |
| 207 fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords && |
| 208 ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0; |
| 209 |
189 fDescInfo.fReadsDst = false; | 210 fDescInfo.fReadsDst = false; |
190 fDescInfo.fReadsFragPosition = false; | 211 fDescInfo.fReadsFragPosition = false; |
191 | 212 |
192 if (flags & GrXferProcessor::kClearColorStages_OptFlag) { | 213 for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) { |
193 fDescInfo.fInputColorIsUsed = true; | 214 const GrFragmentStage& stage = ds.getColorStage(s); |
194 *firstColorStageIdx = ds.numColorStages(); | 215 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPositi
on); |
195 fDescInfo.fHasVertexColor = false; | |
196 } else { | |
197 fDescInfo.fReadsDst = colorPOI.readsDst(); | |
198 fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition(); | |
199 } | 216 } |
200 | 217 for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) { |
201 if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) { | 218 const GrFragmentStage& stage = ds.getCoverageStage(s); |
202 fDescInfo.fInputCoverageIsUsed = true; | 219 get_stage_stats(stage, &fDescInfo.fReadsDst, &fDescInfo.fReadsFragPositi
on); |
203 *firstCoverageStageIdx = ds.numCoverageStages(); | 220 } |
204 fDescInfo.fHasVertexCoverage = false; | 221 if (ds.hasGeometryProcessor()) { |
205 } else { | 222 const GrGeometryProcessor& gp = *ds.getGeometryProcessor(); |
206 if (coveragePOI.readsDst()) { | 223 fDescInfo.fReadsFragPosition = fDescInfo.fReadsFragPosition || gp.willRe
adFragmentPosition(); |
207 fDescInfo.fReadsDst = true; | |
208 } | |
209 if (coveragePOI.readsFragPosition()) { | |
210 fDescInfo.fReadsFragPosition = true; | |
211 } | |
212 } | 224 } |
213 } | 225 } |
214 | 226 |
215 void GrOptDrawState::finalize(GrGpu* gpu) { | 227 void GrOptDrawState::finalize(GrGpu* gpu) { |
216 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc); | 228 gpu->buildProgramDesc(*this, fDescInfo, fDrawType, &fDesc); |
217 fFinalized = true; | 229 fFinalized = true; |
218 } | 230 } |
219 | 231 |
220 //////////////////////////////////////////////////////////////////////////////// | 232 //////////////////////////////////////////////////////////////////////////////// |
221 | 233 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 SkASSERT(this->numFragmentStages() == that.numFragmentStages()); | 274 SkASSERT(this->numFragmentStages() == that.numFragmentStages()); |
263 for (int i = 0; i < this->numFragmentStages(); i++) { | 275 for (int i = 0; i < this->numFragmentStages(); i++) { |
264 | 276 |
265 if (this->getFragmentStage(i) != that.getFragmentStage(i)) { | 277 if (this->getFragmentStage(i) != that.getFragmentStage(i)) { |
266 return false; | 278 return false; |
267 } | 279 } |
268 } | 280 } |
269 return true; | 281 return true; |
270 } | 282 } |
271 | 283 |
OLD | NEW |