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