Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrOptDrawState.cpp
1 /*
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"
11 #include "GrDrawTargetCaps.h"
12 #include "gl/GrGpuGL.h"
13
14 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
15                                BlendOptFlags blendOptFlags,
16                                GrBlendCoeff optSrcCoeff,
17                                GrBlendCoeff optDstCoeff,
18                                GrGpu* gpu,
19                                const GrDeviceCoordTexture* dstCopy,
20                                GrGpu::DrawType drawType) {
21     fRenderTarget.set(SkSafeRef(drawState.getRenderTarget()), kWrite_GrIOType);
22     fColor = drawState.getColor();
23     fCoverage = drawState.getCoverage();
24     fViewMatrix = drawState.getViewMatrix();
25     fBlendConstant = drawState.getBlendConstant();
26     fFlagBits = drawState.getFlagBits();
27     fVAPtr = drawState.getVertexAttribs();
28     fVACount = drawState.getVertexAttribCount();
29     fVAStride = drawState.getVertexStride();
30     fStencilSettings = drawState.getStencil();
31     fDrawFace = (DrawFace)drawState.getDrawFace();
32     fBlendOptFlags = blendOptFlags;
33     fSrcBlend = optSrcCoeff;
34     fDstBlend = optDstCoeff;
35     GrProgramDesc::DescInfo descInfo;
36
37     memcpy(descInfo.fFixedFunctionVertexAttribIndices,
38            drawState.getFixedFunctionVertexAttribIndices(),
39            sizeof(descInfo.fFixedFunctionVertexAttribIndices));
40
41     descInfo.fInputColorIsUsed = true;
42     descInfo.fInputCoverageIsUsed = true;
43
44     int firstColorStageIdx = 0;
45     int firstCoverageStageIdx = 0;
46     bool separateCoverageFromColor;
47
48     uint8_t fixedFunctionVAToRemove = 0;
49
50     this->computeEffectiveColorStages(drawState, &descInfo, &firstColorStageIdx,
51                                       &fixedFunctionVAToRemove);
52     this->computeEffectiveCoverageStages(drawState, &descInfo, &firstCoverageStageIdx);
53     this->adjustFromBlendOpts(drawState, &descInfo, &firstColorStageIdx, &firstCoverageStageIdx,
54                               &fixedFunctionVAToRemove);
55     // Should not be setting any more FFVA to be removed at this point
56     if (0 != fixedFunctionVAToRemove) {
57         this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo);
58     }
59     this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo);
60     this->setOutputStateInfo(drawState, *gpu->caps(), firstCoverageStageIdx, &descInfo,
61                              &separateCoverageFromColor);
62
63     // Copy GeometryProcesssor from DS or ODS
64     if (drawState.hasGeometryProcessor()) {
65         fGeometryProcessor.initAndRef(drawState.fGeometryProcessor);
66     } else {
67         fGeometryProcessor.reset(NULL);
68     }
69
70     // Copy Color Stages from DS to ODS
71     if (firstColorStageIdx < drawState.numColorStages()) {
72         fFragmentStages.reset(&drawState.getColorStage(firstColorStageIdx),
73                               drawState.numColorStages() - firstColorStageIdx);
74     } else {
75         fFragmentStages.reset();
76     }
77
78     fNumColorStages = fFragmentStages.count();
79
80     // Copy Coverage Stages from DS to ODS
81     if (firstCoverageStageIdx < drawState.numCoverageStages()) {
82         fFragmentStages.push_back_n(drawState.numCoverageStages() - firstCoverageStageIdx,
83                                     &drawState.getCoverageStage(firstCoverageStageIdx));
84         if (!separateCoverageFromColor) {
85             fNumColorStages = fFragmentStages.count();
86         }
87     }
88
89     // now create a key
90     gpu->buildProgramDesc(*this, descInfo, drawType, dstCopy, &fDesc);
91 };
92
93 GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState,
94                                        GrGpu* gpu,
95                                        const GrDeviceCoordTexture* dstCopy,
96                                        GrGpu::DrawType drawType) {
97     const GrDrawTargetCaps& caps = *gpu->caps();
98     if (NULL == drawState.fCachedOptState || caps.getUniqueID() != drawState.fCachedCapsID) {
99         GrBlendCoeff srcCoeff;
100         GrBlendCoeff dstCoeff;
101         BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false,
102                                                                           &srcCoeff,
103                                                                           &dstCoeff);
104
105         // If our blend coeffs are set to 0,1 we know we will not end up drawing unless we are
106         // stenciling. When path rendering the stencil settings are not always set on the draw state
107         // so we must check the draw type. In cases where we will skip drawing we simply return a
108         // null GrOptDrawState.
109         if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff &&
110             !drawState.getStencil().doesWrite() && GrGpu::kStencilPath_DrawType != drawType) {
111             return NULL;
112         }
113
114         drawState.fCachedOptState = SkNEW_ARGS(GrOptDrawState, (drawState, blendFlags, srcCoeff,
115                                                                 dstCoeff, gpu, dstCopy, drawType));
116         drawState.fCachedCapsID = caps.getUniqueID();
117     } else {
118 #ifdef SK_DEBUG
119         GrBlendCoeff srcCoeff;
120         GrBlendCoeff dstCoeff;
121         BlendOptFlags blendFlags = (BlendOptFlags) drawState.getBlendOpts(false,
122                                                                           &srcCoeff,
123                                                                           &dstCoeff);
124         SkASSERT(GrOptDrawState(drawState, blendFlags, srcCoeff, dstCoeff, gpu, dstCopy,
125                                 drawType) == *drawState.fCachedOptState);
126 #endif
127     }
128     drawState.fCachedOptState->ref();
129     return drawState.fCachedOptState;
130 }
131
132 void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
133                                         const GrDrawTargetCaps& caps,
134                                         int firstCoverageStageIdx,
135                                         GrProgramDesc::DescInfo* descInfo,
136                                         bool* separateCoverageFromColor) {
137     // Set this default and then possibly change our mind if there is coverage.
138     descInfo->fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
139     descInfo->fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
140
141     // If we do have coverage determine whether it matters.
142     *separateCoverageFromColor = this->hasGeometryProcessor();
143     if (!this->isCoverageDrawing() &&
144         (ds.numCoverageStages() - firstCoverageStageIdx > 0 ||
145          ds.hasGeometryProcessor() ||
146          descInfo->hasCoverageVertexAttribute())) {
147
148         if (caps.dualSourceBlendingSupport()) {
149             if (kZero_GrBlendCoeff == fDstBlend) {
150                 // write the coverage value to second color
151                 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
152                 *separateCoverageFromColor = true;
153                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
154             } else if (kSA_GrBlendCoeff == fDstBlend) {
155                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
156                 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
157                 *separateCoverageFromColor = true;
158                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
159             } else if (kSC_GrBlendCoeff == fDstBlend) {
160                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
161                 descInfo->fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
162                 *separateCoverageFromColor = true;
163                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
164             }
165         } else if (descInfo->fReadsDst &&
166                    kOne_GrBlendCoeff == fSrcBlend &&
167                    kZero_GrBlendCoeff == fDstBlend) {
168             descInfo->fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
169             *separateCoverageFromColor = true;
170         }
171     }
172 }
173
174 void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds,
175                                          GrProgramDesc::DescInfo* descInfo,
176                                          int* firstColorStageIdx,
177                                          int* firstCoverageStageIdx,
178                                          uint8_t* fixedFunctionVAToRemove) {
179     switch (fBlendOptFlags) {
180         case kNone_BlendOpt:
181         case kSkipDraw_BlendOptFlag:
182             break;
183         case kCoverageAsAlpha_BlendOptFlag:
184             fFlagBits |= kCoverageDrawing_StateBit;
185             break;
186         case kEmitCoverage_BlendOptFlag:
187             fColor = 0xffffffff;
188             descInfo->fInputColorIsUsed = true;
189             *firstColorStageIdx = ds.numColorStages();
190             *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
191             break;
192         case kEmitTransBlack_BlendOptFlag:
193             fColor = 0;
194             fCoverage = 0xff;
195             descInfo->fInputColorIsUsed = true;
196             descInfo->fInputCoverageIsUsed = true;
197             *firstColorStageIdx = ds.numColorStages();
198             *firstCoverageStageIdx = ds.numCoverageStages();
199             *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
200                                          0x1 << kCoverage_GrVertexAttribBinding);
201             break;
202         default:
203             SkFAIL("Unknown BlendOptFlag");
204     }
205 }
206
207 void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag,
208                                                       GrProgramDesc::DescInfo* descInfo) {
209     int numToRemove = 0;
210     uint8_t maskCheck = 0x1;
211     // Count the number of vertex attributes that we will actually remove
212     for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
213         if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) {
214             ++numToRemove;
215         }
216         maskCheck <<= 1;
217     }
218
219     fOptVA.reset(fVACount - numToRemove);
220
221     GrVertexAttrib* dst = fOptVA.get();
222     const GrVertexAttrib* src = fVAPtr;
223
224     for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
225         const GrVertexAttrib& currAttrib = *src;
226         if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
227             uint8_t maskCheck = 0x1 << currAttrib.fBinding;
228             if (maskCheck & removeVAFlag) {
229                 SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
230                 descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
231                 continue;
232             }
233             descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
234         }
235         memcpy(dst, src, sizeof(GrVertexAttrib));
236         ++newIdx;
237         ++dst;
238     }
239     fVACount -= numToRemove;
240     fVAPtr = fOptVA.get();
241 }
242
243 void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds,
244                                                  GrProgramDesc::DescInfo* descInfo,
245                                                  int* firstColorStageIdx,
246                                                  uint8_t* fixedFunctionVAToRemove) {
247     // Set up color and flags for ConstantColorComponent checks
248     GrProcessor::InvariantOutput inout;
249     inout.fIsSingleComponent = false;
250     if (!descInfo->hasColorVertexAttribute()) {
251         inout.fColor = ds.getColor();
252         inout.fValidFlags = kRGBA_GrColorComponentFlags;
253     } else {
254         if (ds.vertexColorsAreOpaque()) {
255             inout.fColor = 0xFF << GrColor_SHIFT_A;
256             inout.fValidFlags = kA_GrColorComponentFlag;
257         } else {
258             inout.fValidFlags = 0;
259             // not strictly necessary but we get false alarms from tools about uninit.
260             inout.fColor = 0;
261         }
262     }
263
264     for (int i = 0; i < ds.numColorStages(); ++i) {
265         const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
266         fp->computeInvariantOutput(&inout);
267         if (!inout.fWillUseInputColor) {
268             *firstColorStageIdx = i;
269             descInfo->fInputColorIsUsed = false;
270         }
271         if (kRGBA_GrColorComponentFlags == inout.fValidFlags) {
272             *firstColorStageIdx = i + 1;
273             fColor = inout.fColor;
274             descInfo->fInputColorIsUsed = true;
275             *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
276             // Since we are clearing all previous color stages we are in a state where we have found
277             // zero stages that don't multiply the inputColor.
278             inout.fNonMulStageFound = false;
279         }
280     }
281 }
282
283 void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds,
284                                                     GrProgramDesc::DescInfo* descInfo,
285                                                     int* firstCoverageStageIdx) {
286     // We do not try to optimize out constantColor coverage effects here. It is extremely rare
287     // to have a coverage effect that returns a constant value for all four channels. Thus we
288     // save having to make extra virtual calls by not checking for it.
289
290     // Don't do any optimizations on coverage stages. It should not be the case where we do not use
291     // input coverage in an effect
292 #ifdef OptCoverageStages
293     GrProcessor::InvariantOutput inout;
294     for (int i = 0; i < ds.numCoverageStages(); ++i) {
295         const GrFragmentProcessor* fp = ds.getCoverageStage(i).getProcessor();
296         fp->computeInvariantOutput(&inout);
297         if (!inout.fWillUseInputColor) {
298             *firstCoverageStageIdx = i;
299             descInfo->fInputCoverageIsUsed = false;
300         }
301     }
302 #endif
303 }
304
305 static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
306     if (stage.getProcessor()->willReadDstColor()) {
307         *readsDst = true;
308     }
309     if (stage.getProcessor()->willReadFragmentPosition()) {
310         *readsFragPosition = true;
311     }
312 }
313
314 void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
315                                    int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) {
316     // We will need a local coord attrib if there is one currently set on the optState and we are
317     // actually generating some effect code
318     descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() &&
319         ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
320
321     descInfo->fReadsDst = false;
322     descInfo->fReadsFragPosition = false;
323
324     for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
325         const GrFragmentStage& stage = ds.getColorStage(s);
326         get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
327     }
328     for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
329         const GrFragmentStage& stage = ds.getCoverageStage(s);
330         get_stage_stats(stage, &descInfo->fReadsDst, &descInfo->fReadsFragPosition);
331     }
332     if (ds.hasGeometryProcessor()) {
333         const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
334         descInfo->fReadsFragPosition = descInfo->fReadsFragPosition || gp.willReadFragmentPosition();
335     }
336 }
337
338 ////////////////////////////////////////////////////////////////////////////////
339
340 bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
341     return this->isEqual(that);
342 }
343
344 bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
345     if (this->fDesc != that.fDesc) {
346         return false;
347     }
348     bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1;
349     if (!usingVertexColors && this->fColor != that.fColor) {
350         return false;
351     }
352
353     if (this->getRenderTarget() != that.getRenderTarget() ||
354         !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
355         this->fSrcBlend != that.fSrcBlend ||
356         this->fDstBlend != that.fDstBlend ||
357         this->fBlendConstant != that.fBlendConstant ||
358         this->fFlagBits != that.fFlagBits ||
359         this->fVACount != that.fVACount ||
360         this->fVAStride != that.fVAStride ||
361         memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
362         this->fStencilSettings != that.fStencilSettings ||
363         this->fDrawFace != that.fDrawFace) {
364         return false;
365     }
366
367     bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1;
368     if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
369         return false;
370     }
371
372     if (this->hasGeometryProcessor()) {
373         if (!that.hasGeometryProcessor()) {
374             return false;
375         } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
376             return false;
377         }
378     } else if (that.hasGeometryProcessor()) {
379         return false;
380     }
381
382     bool explicitLocalCoords = this->fDesc.header().fLocalCoordAttributeIndex != -1;
383     for (int i = 0; i < this->numFragmentStages(); i++) {
384         if (!GrFragmentStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i),
385                                             explicitLocalCoords)) {
386             return false;
387         }
388     }
389     return true;
390 }
391