Upstream version 10.39.225.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 "GrGpu.h"
13
14 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
15                                BlendOptFlags blendOptFlags,
16                                GrBlendCoeff optSrcCoeff,
17                                GrBlendCoeff optDstCoeff,
18                                const GrDrawTargetCaps& caps) : INHERITED(drawState) {
19     fColor = drawState.getColor();
20     fCoverage = drawState.getCoverage();
21     fViewMatrix = drawState.getViewMatrix();
22     fBlendConstant = drawState.getBlendConstant();
23     fFlagBits = drawState.getFlagBits();
24     fVAPtr = drawState.getVertexAttribs();
25     fVACount = drawState.getVertexAttribCount();
26     fVAStride = drawState.getVertexStride();
27     fStencilSettings = drawState.getStencil();
28     fDrawFace = drawState.getDrawFace();
29     fBlendOptFlags = blendOptFlags;
30     fSrcBlend = optSrcCoeff;
31     fDstBlend = optDstCoeff;
32
33     memcpy(fFixedFunctionVertexAttribIndices,
34             drawState.getFixedFunctionVertexAttribIndices(),
35             sizeof(fFixedFunctionVertexAttribIndices));
36
37
38     fInputColorIsUsed = true;
39     fInputCoverageIsUsed = true;
40
41     if (drawState.hasGeometryProcessor()) {
42         fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*drawState.getGeometryProcessor())));
43     } else {
44         fGeometryProcessor.reset(NULL);
45     }
46
47     this->copyEffectiveColorStages(drawState);
48     this->copyEffectiveCoverageStages(drawState);
49     this->adjustFromBlendOpts();
50     this->getStageStats();
51     this->setOutputStateInfo(caps);
52 };
53
54 void GrOptDrawState::setOutputStateInfo(const GrDrawTargetCaps& caps) {
55     // Set this default and then possibly change our mind if there is coverage.
56     fPrimaryOutputType = kModulate_PrimaryOutputType;
57     fSecondaryOutputType = kNone_SecondaryOutputType;
58
59     // If we do have coverage determine whether it matters.
60     bool separateCoverageFromColor = this->hasGeometryProcessor();
61     if (!this->isCoverageDrawing() &&
62         (this->numCoverageStages() > 0 ||
63          this->hasGeometryProcessor() ||
64          this->hasCoverageVertexAttribute())) {
65
66         if (caps.dualSourceBlendingSupport()) {
67             if (kZero_GrBlendCoeff == fDstBlend) {
68                 // write the coverage value to second color
69                 fSecondaryOutputType =  kCoverage_SecondaryOutputType;
70                 separateCoverageFromColor = true;
71                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
72             } else if (kSA_GrBlendCoeff == fDstBlend) {
73                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
74                 fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
75                 separateCoverageFromColor = true;
76                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
77             } else if (kSC_GrBlendCoeff == fDstBlend) {
78                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
79                 fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
80                 separateCoverageFromColor = true;
81                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
82             }
83         } else if (fReadsDst &&
84                    kOne_GrBlendCoeff == fSrcBlend &&
85                    kZero_GrBlendCoeff == fDstBlend) {
86             fPrimaryOutputType = kCombineWithDst_PrimaryOutputType;
87             separateCoverageFromColor = true;
88         }
89     }
90
91     // TODO: Once we have flag to know if we only multiply on stages, only push coverage into color
92     // stages if everything is multipy
93     if (!separateCoverageFromColor) {
94         for (int s = 0; s < this->numCoverageStages(); ++s) {
95             fColorStages.push_back(this->getCoverageStage(s));
96         }
97         fCoverageStages.reset();
98     }
99 }
100
101 void GrOptDrawState::adjustFromBlendOpts() {
102
103     switch (fBlendOptFlags) {
104         case kNone_BlendOpt:
105         case kSkipDraw_BlendOptFlag:
106             break;
107         case kCoverageAsAlpha_BlendOptFlag:
108             fFlagBits |= kCoverageDrawing_StateBit;
109             break;
110         case kEmitCoverage_BlendOptFlag:
111             fColor = 0xffffffff;
112             fInputColorIsUsed = true;
113             fColorStages.reset();
114             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
115             break;
116         case kEmitTransBlack_BlendOptFlag:
117             fColor = 0;
118             fCoverage = 0xff;
119             fInputColorIsUsed = true;
120             fInputCoverageIsUsed = true;
121             fColorStages.reset();
122             fCoverageStages.reset();
123             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
124                                                    0x1 << kCoverage_GrVertexAttribBinding);
125             break;
126         default:
127             SkFAIL("Unknown BlendOptFlag");
128
129     }
130 }
131
132 void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
133     int numToRemove = 0;
134     uint8_t maskCheck = 0x1;
135     // Count the number of vertex attributes that we will actually remove
136     for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
137         if ((maskCheck & removeVAFlag) && -1 != fFixedFunctionVertexAttribIndices[i]) {
138             ++numToRemove;
139         }
140         maskCheck <<= 1;
141     }
142
143     fOptVA.reset(fVACount - numToRemove);
144
145     GrVertexAttrib* dst = fOptVA.get();
146     const GrVertexAttrib* src = fVAPtr;
147
148     for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
149         const GrVertexAttrib& currAttrib = *src;
150         if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
151             uint8_t maskCheck = 0x1 << currAttrib.fBinding;
152             if (maskCheck & removeVAFlag) {
153                 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
154                 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
155                 continue;
156             }
157             fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
158         }
159         memcpy(dst, src, sizeof(GrVertexAttrib));
160         ++newIdx;
161         ++dst;
162     }
163     fVACount -= numToRemove;
164     fVAPtr = fOptVA.get();
165 }
166
167 void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
168     int firstColorStage = 0;
169
170     // Set up color and flags for ConstantColorComponent checks
171     GrColor color;
172     uint32_t validComponentFlags;
173     if (!this->hasColorVertexAttribute()) {
174         color = ds.getColor();
175         validComponentFlags = kRGBA_GrColorComponentFlags;
176     } else {
177         if (ds.vertexColorsAreOpaque()) {
178             color = 0xFF << GrColor_SHIFT_A;
179             validComponentFlags = kA_GrColorComponentFlag;
180         } else {
181             validComponentFlags = 0;
182             color = 0; // not strictly necessary but we get false alarms from tools about uninit.
183         }
184     }
185
186     for (int i = 0; i < ds.numColorStages(); ++i) {
187         const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
188         if (!fp->willUseInputColor()) {
189             firstColorStage = i;
190             fInputColorIsUsed = false;
191         }
192         fp->getConstantColorComponents(&color, &validComponentFlags);
193         if (kRGBA_GrColorComponentFlags == validComponentFlags) {
194             firstColorStage = i + 1;
195             fColor = color;
196             fInputColorIsUsed = true;
197             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
198         }
199     }
200     if (firstColorStage < ds.numColorStages()) {
201         fColorStages.reset(&ds.getColorStage(firstColorStage),
202                            ds.numColorStages() - firstColorStage);
203     } else {
204         fColorStages.reset();
205     }
206 }
207
208 void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
209     int firstCoverageStage = 0;
210
211     // We do not try to optimize out constantColor coverage effects here. It is extremely rare
212     // to have a coverage effect that returns a constant value for all four channels. Thus we
213     // save having to make extra virtual calls by not checking for it.
214
215     // Don't do any optimizations on coverage stages. It should not be the case where we do not use
216     // input coverage in an effect
217 #ifdef OptCoverageStages
218     for (int i = 0; i < ds.numCoverageStages(); ++i) {
219         const GrProcessor* processor = ds.getCoverageStage(i).getProcessor();
220         if (!processor->willUseInputColor()) {
221             firstCoverageStage = i;
222             fInputCoverageIsUsed = false;
223         }
224     }
225 #endif
226     if (ds.numCoverageStages() > 0) {
227         fCoverageStages.reset(&ds.getCoverageStage(firstCoverageStage),
228                               ds.numCoverageStages() - firstCoverageStage);
229     } else {
230         fCoverageStages.reset();
231     }
232 }
233
234 static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
235     if (stage.getFragmentProcessor()->willReadDstColor()) {
236         *readsDst = true;
237     }
238     if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
239         *readsFragPosition = true;
240     }
241 }
242
243 void GrOptDrawState::getStageStats() {
244     // We will need a local coord attrib if there is one currently set on the optState and we are
245     // actually generating some effect code
246     fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
247
248     fReadsDst = false;
249     fReadsFragPosition = false;
250
251     for (int s = 0; s < this->numColorStages(); ++s) {
252         const GrFragmentStage& stage = this->getColorStage(s);
253         get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
254     }
255     for (int s = 0; s < this->numCoverageStages(); ++s) {
256         const GrFragmentStage& stage = this->getCoverageStage(s);
257         get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
258     }
259     if (this->hasGeometryProcessor()) {
260         const GrGeometryStage& stage = *this->getGeometryProcessor();
261         fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition();
262     }
263 }
264
265 bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
266     return this->isEqual(that);
267 }
268