blob: bf68deff77d4a14c299e68e66b811a7c620117c3 [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrBinHashKey.h"
junov@google.comf93e7172011-03-31 21:26:24 +000018#include "GrGLProgram.h"
19#include "GrGpuGLShaders.h"
20#include "GrGpuVertex.h"
21#include "GrMemory.h"
22#include "GrNoncopyable.h"
23#include "GrStringBuilder.h"
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000024#include "GrRandom.h"
junov@google.comf93e7172011-03-31 21:26:24 +000025
junov@google.comf93e7172011-03-31 21:26:24 +000026#define SKIP_CACHE_CHECK true
27#define GR_UINT32_MAX static_cast<uint32_t>(-1)
28
junov@google.comf93e7172011-03-31 21:26:24 +000029#include "GrTHashCache.h"
30
31class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable {
32private:
33 class Entry;
34
35#if GR_DEBUG
36 typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug
37#else
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +000038 typedef GrBinHashKey<Entry, 64> ProgramHashKey;
junov@google.comf93e7172011-03-31 21:26:24 +000039#endif
40
41 class Entry : public ::GrNoncopyable {
42 public:
43 Entry() {}
junov@google.comf93e7172011-03-31 21:26:24 +000044 void copyAndTakeOwnership(Entry& entry) {
45 fProgramData.copyAndTakeOwnership(entry.fProgramData);
46 fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000047 fLRUStamp = entry.fLRUStamp;
junov@google.comf93e7172011-03-31 21:26:24 +000048 }
49
50 public:
51 int compare(const ProgramHashKey& key) const { return fKey.compare(key); }
52
53 public:
54 GrGLProgram::CachedData fProgramData;
55 ProgramHashKey fKey;
56 unsigned int fLRUStamp;
57 };
58
59 GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
60
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000061 // We may have kMaxEntries+1 shaders in the GL context because
62 // we create a new shader before evicting from the cache.
junov@google.comf93e7172011-03-31 21:26:24 +000063 enum {
64 kMaxEntries = 32
65 };
66 Entry fEntries[kMaxEntries];
67 int fCount;
68 unsigned int fCurrLRUStamp;
69
70public:
71 ProgramCache()
72 : fCount(0)
73 , fCurrLRUStamp(0) {
74 }
75
76 ~ProgramCache() {
77 for (int i = 0; i < fCount; ++i) {
78 GrGpuGLShaders::DeleteProgram(&fEntries[i].fProgramData);
79 }
80 }
81
82 void abandon() {
83 fCount = 0;
84 }
85
86 void invalidateViewMatrices() {
87 for (int i = 0; i < fCount; ++i) {
88 // set to illegal matrix
89 fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix();
90 }
91 }
92
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000093 GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000094 Entry newEntry;
95 while (newEntry.fKey.doPass()) {
96 desc.buildKey(newEntry.fKey);
junov@google.comf93e7172011-03-31 21:26:24 +000097 }
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000098 Entry* entry = fHashCache.find(newEntry.fKey);
junov@google.comf93e7172011-03-31 21:26:24 +000099 if (NULL == entry) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +0000100 if (!desc.genProgram(&newEntry.fProgramData)) {
101 return NULL;
102 }
junov@google.comf93e7172011-03-31 21:26:24 +0000103 if (fCount < kMaxEntries) {
104 entry = fEntries + fCount;
105 ++fCount;
106 } else {
107 GrAssert(kMaxEntries == fCount);
108 entry = fEntries;
109 for (int i = 1; i < kMaxEntries; ++i) {
110 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
111 entry = fEntries + i;
112 }
113 }
114 fHashCache.remove(entry->fKey, entry);
115 GrGpuGLShaders::DeleteProgram(&entry->fProgramData);
116 }
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +0000117 entry->copyAndTakeOwnership(newEntry);
junov@google.comf93e7172011-03-31 21:26:24 +0000118 fHashCache.insert(entry->fKey, entry);
119 }
120
121 entry->fLRUStamp = fCurrLRUStamp;
122 if (GR_UINT32_MAX == fCurrLRUStamp) {
123 // wrap around! just trash our LRU, one time hit.
124 for (int i = 0; i < fCount; ++i) {
125 fEntries[i].fLRUStamp = 0;
126 }
127 }
128 ++fCurrLRUStamp;
129 return &entry->fProgramData;
130 }
131};
132
133void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) {
134 GR_GL(DeleteShader(programData->fVShaderID));
135 GR_GL(DeleteShader(programData->fFShaderID));
136 GR_GL(DeleteProgram(programData->fProgramID));
137 GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));)
138}
139
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000140void GrGpuGLShaders::ProgramUnitTest() {
141
142 static const int STAGE_OPTS[] = {
143 0,
144 GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit,
145 GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping
146 };
147 static const GrGLProgram::ProgramDesc::StageDesc::Modulation STAGE_MODULATES[] = {
148 GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation,
149 GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation
150 };
151 static const GrGLProgram::ProgramDesc::StageDesc::CoordMapping STAGE_COORD_MAPPINGS[] = {
152 GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping,
153 GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping,
154 GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping,
155 GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping
156 };
157 static const GrGLProgram::ProgramDesc::StageDesc::FetchMode FETCH_MODES[] = {
158 GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode,
159 GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode,
160 };
161 GrGLProgram program;
162 GrGLProgram::ProgramDesc& pdesc = program.fProgramDesc;
163
164 static const int NUM_TESTS = 512;
165
166 // GrRandoms nextU() values have patterns in the low bits
167 // So using nextU() % array_count might never take some values.
168 GrRandom random;
169 for (int t = 0; t < NUM_TESTS; ++t) {
170
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000171#if 0
172 GrPrintf("\nTest Program %d\n-------------\n", t);
173 static const int stop = -1;
174 if (t == stop) {
175 int breakpointhere = 9;
176 }
177#endif
178
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000179 pdesc.fVertexLayout = 0;
180 pdesc.fEmitsPointSize = random.nextF() > .5f;
181 float colorType = random.nextF();
182 if (colorType < 1.f / 3.f) {
183 pdesc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
184 } else if (colorType < 2.f / 3.f) {
185 pdesc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
186 } else {
187 pdesc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
188 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000189
190 int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt));
191 pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx;
192
193 idx = (int)(random.nextF() * (kNumStages+1));
194 pdesc.fFirstCoverageStage = idx;
195
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000196 pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1));
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000197
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000198 if (fDualSourceBlendingSupport) {
199 pdesc.fDualSrcOutput =
200 (GrGLProgram::ProgramDesc::DualSrcOutput)
201 (int)(random.nextF() * GrGLProgram::ProgramDesc::kDualSrcOutputCnt);
202 } else {
203 pdesc.fDualSrcOutput =
204 GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
205 }
206
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000207 for (int s = 0; s < kNumStages; ++s) {
208 // enable the stage?
209 if (random.nextF() > .5f) {
210 // use separate tex coords?
211 if (random.nextF() > .5f) {
212 int t = (int)(random.nextF() * kMaxTexCoords);
213 pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
214 } else {
215 pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
216 }
217 }
218 // use text-formatted verts?
219 if (random.nextF() > .5f) {
220 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
221 }
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000222 pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000223 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
224 pdesc.fStages[s].fOptFlags = STAGE_OPTS[idx];
225 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
226 pdesc.fStages[s].fModulation = STAGE_MODULATES[idx];
227 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
228 pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[idx];
229 idx = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES));
230 pdesc.fStages[s].fFetchMode = FETCH_MODES[idx];
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000231 }
232 GrGLProgram::CachedData cachedData;
233 program.genProgram(&cachedData);
234 DeleteProgram(&cachedData);
235 bool again = false;
236 if (again) {
237 program.genProgram(&cachedData);
238 DeleteProgram(&cachedData);
239 }
240 }
241}
242
junov@google.comf93e7172011-03-31 21:26:24 +0000243GrGpuGLShaders::GrGpuGLShaders() {
244
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000245 resetContext();
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000246 int major, minor;
247 gl_version(&major, &minor);
248
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000249 f4X4DownsampleFilterSupport = true;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000250 if (GR_GL_SUPPORT_DESKTOP) {
251 fDualSourceBlendingSupport =
252 major > 3 ||(3 == major && 3 <= minor) ||
253 has_gl_extension("GL_ARB_blend_func_extended");
254 } else {
255 fDualSourceBlendingSupport = false;
256 }
junov@google.comf93e7172011-03-31 21:26:24 +0000257
258 fProgramData = NULL;
259 fProgramCache = new ProgramCache();
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000260
261#if 0
262 ProgramUnitTest();
263#endif
junov@google.comf93e7172011-03-31 21:26:24 +0000264}
265
266GrGpuGLShaders::~GrGpuGLShaders() {
267 delete fProgramCache;
268}
269
270const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
junov@google.comf93e7172011-03-31 21:26:24 +0000271 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000272
273 if (GrGLProgram::kSetAsAttribute ==
274 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
275 return fHWDrawState.fSamplerStates[stage].getMatrix();
276 } else {
277 return fProgramData->fTextureMatrices[stage];
278 }
junov@google.comf93e7172011-03-31 21:26:24 +0000279}
280
281void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000282 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000283 if (GrGLProgram::kSetAsAttribute ==
284 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
285 fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
286 } else {
287 fProgramData->fTextureMatrices[stage] = matrix;
288 }
junov@google.comf93e7172011-03-31 21:26:24 +0000289}
290
291void GrGpuGLShaders::resetContext() {
292 INHERITED::resetContext();
junov@google.comf93e7172011-03-31 21:26:24 +0000293
junov@google.comf93e7172011-03-31 21:26:24 +0000294 fHWGeometryState.fVertexLayout = 0;
295 fHWGeometryState.fVertexOffset = ~0;
bsalomon@google.com91961302011-05-09 18:39:58 +0000296 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000297 for (int t = 0; t < kMaxTexCoords; ++t) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000298 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000299 }
bsalomon@google.com91961302011-05-09 18:39:58 +0000300 GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000301
302 fHWProgramID = 0;
303}
304
305void GrGpuGLShaders::flushViewMatrix() {
306 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.comcc4dac32011-05-10 13:52:42 +0000307 GrMatrix m;
308 m.setAll(
junov@google.comf93e7172011-03-31 21:26:24 +0000309 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
310 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
311 0, 0, GrMatrix::I()[8]);
312 m.setConcat(m, fCurrDrawState.fViewMatrix);
313
314 // ES doesn't allow you to pass true to the transpose param,
315 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000316 GrGLfloat mt[] = {
317 GrScalarToFloat(m[GrMatrix::kMScaleX]),
318 GrScalarToFloat(m[GrMatrix::kMSkewY]),
319 GrScalarToFloat(m[GrMatrix::kMPersp0]),
320 GrScalarToFloat(m[GrMatrix::kMSkewX]),
321 GrScalarToFloat(m[GrMatrix::kMScaleY]),
322 GrScalarToFloat(m[GrMatrix::kMPersp1]),
323 GrScalarToFloat(m[GrMatrix::kMTransX]),
324 GrScalarToFloat(m[GrMatrix::kMTransY]),
325 GrScalarToFloat(m[GrMatrix::kMPersp2])
junov@google.comf93e7172011-03-31 21:26:24 +0000326 };
bsalomon@google.com91961302011-05-09 18:39:58 +0000327
328 if (GrGLProgram::kSetAsAttribute ==
329 fProgramData->fUniLocations.fViewMatrixUni) {
330 int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
331 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
332 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
333 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
334 } else {
335 GrAssert(GrGLProgram::kUnusedUniform !=
336 fProgramData->fUniLocations.fViewMatrixUni);
337 GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
338 1, false, mt));
339 }
junov@google.comf93e7172011-03-31 21:26:24 +0000340}
341
junov@google.com6acc9b32011-05-16 18:32:07 +0000342void GrGpuGLShaders::flushTextureDomain(int s) {
343 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
344 if (GrGLProgram::kUnusedUniform != uni) {
345 const GrRect &texDom =
346 fCurrDrawState.fSamplerStates[s].getTextureDomain();
347
348 float values[4] = {
349 GrScalarToFloat(texDom.left()),
350 GrScalarToFloat(texDom.top()),
351 GrScalarToFloat(texDom.right()),
352 GrScalarToFloat(texDom.bottom())
353 };
354
355 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
356 GrGLTexture::Orientation orientation = texture->orientation();
357
358 // vertical flip if necessary
359 if (GrGLTexture::kBottomUp_Orientation == orientation) {
360 values[1] = 1.0f - values[1];
361 values[3] = 1.0f - values[3];
362 }
363
364 values[0] *= SkScalarToFloat(texture->contentScaleX());
365 values[2] *= SkScalarToFloat(texture->contentScaleX());
366 values[1] *= SkScalarToFloat(texture->contentScaleY());
367 values[3] *= SkScalarToFloat(texture->contentScaleY());
368
369 GR_GL(Uniform4fv(uni, 1, values));
370 }
371}
372
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000373void GrGpuGLShaders::flushTextureMatrix(int s) {
junov@google.com6acc9b32011-05-16 18:32:07 +0000374 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000375 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
376 if (NULL != texture) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000377 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000378 (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
379 getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
junov@google.comf93e7172011-03-31 21:26:24 +0000380
bsalomon@google.com91961302011-05-09 18:39:58 +0000381 GrAssert(NULL != fCurrDrawState.fTextures[s]);
junov@google.comf93e7172011-03-31 21:26:24 +0000382
bsalomon@google.com91961302011-05-09 18:39:58 +0000383 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000384
bsalomon@google.com91961302011-05-09 18:39:58 +0000385 GrMatrix m = getSamplerMatrix(s);
386 GrSamplerState::SampleMode mode =
387 fCurrDrawState.fSamplerStates[s].getSampleMode();
388 AdjustTextureMatrix(texture, mode, &m);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000389
bsalomon@google.com91961302011-05-09 18:39:58 +0000390 // ES doesn't allow you to pass true to the transpose param,
391 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000392 GrGLfloat mt[] = {
393 GrScalarToFloat(m[GrMatrix::kMScaleX]),
394 GrScalarToFloat(m[GrMatrix::kMSkewY]),
395 GrScalarToFloat(m[GrMatrix::kMPersp0]),
396 GrScalarToFloat(m[GrMatrix::kMSkewX]),
397 GrScalarToFloat(m[GrMatrix::kMScaleY]),
398 GrScalarToFloat(m[GrMatrix::kMPersp1]),
399 GrScalarToFloat(m[GrMatrix::kMTransX]),
400 GrScalarToFloat(m[GrMatrix::kMTransY]),
401 GrScalarToFloat(m[GrMatrix::kMPersp2])
bsalomon@google.com91961302011-05-09 18:39:58 +0000402 };
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000403
bsalomon@google.com91961302011-05-09 18:39:58 +0000404 if (GrGLProgram::kSetAsAttribute ==
405 fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
406 int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s);
407 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
408 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
409 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
410 } else {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000411 GR_GL(UniformMatrix3fv(uni, 1, false, mt));
bsalomon@google.com91961302011-05-09 18:39:58 +0000412 }
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000413 recordHWSamplerMatrix(s, getSamplerMatrix(s));
414 }
415 }
junov@google.comf93e7172011-03-31 21:26:24 +0000416}
417
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000418void GrGpuGLShaders::flushRadial2(int s) {
junov@google.comf93e7172011-03-31 21:26:24 +0000419
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000420 const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
421 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com91961302011-05-09 18:39:58 +0000422 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000423 (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
424 fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
425 fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
junov@google.comf93e7172011-03-31 21:26:24 +0000426
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000427 GrScalar centerX1 = sampler.getRadial2CenterX1();
428 GrScalar radius0 = sampler.getRadial2Radius0();
junov@google.comf93e7172011-03-31 21:26:24 +0000429
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000430 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
junov@google.comf93e7172011-03-31 21:26:24 +0000431
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000432 float values[6] = {
433 GrScalarToFloat(a),
434 1 / (2.f * values[0]),
435 GrScalarToFloat(centerX1),
436 GrScalarToFloat(radius0),
437 GrScalarToFloat(GrMul(radius0, radius0)),
438 sampler.isRadial2PosRoot() ? 1.f : -1.f
439 };
440 GR_GL(Uniform1fv(uni, 6, values));
441 fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
442 fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0();
443 fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
444 }
445}
446
447void GrGpuGLShaders::flushTexelSize(int s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000448 const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
bsalomon@google.com91961302011-05-09 18:39:58 +0000449 if (GrGLProgram::kUnusedUniform != uni) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000450 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
451 if (texture->allocWidth() != fProgramData->fTextureWidth[s] ||
452 texture->allocHeight() != fProgramData->fTextureWidth[s]) {
453
454 float texelSize[] = {1.f / texture->allocWidth(),
455 1.f / texture->allocHeight()};
456 GR_GL(Uniform2fv(uni, 1, texelSize));
457 }
458 }
junov@google.comf93e7172011-03-31 21:26:24 +0000459}
460
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000461void GrGpuGLShaders::flushEdgeAAData() {
462 const int& uni = fProgramData->fUniLocations.fEdgesUni;
463 if (GrGLProgram::kUnusedUniform != uni) {
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000464 int count = fCurrDrawState.fEdgeAANumEdges;
465 Edge edges[kMaxEdges];
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000466 // Flip the edges in Y
467 float height = fCurrDrawState.fRenderTarget->height();
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000468 for (int i = 0; i < count; ++i) {
469 edges[i] = fCurrDrawState.fEdgeAAEdges[i];
470 float b = edges[i].fY;
471 edges[i].fY = -b;
472 edges[i].fZ += b * height;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000473 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000474 GR_GL(Uniform3fv(uni, count, &edges[0].fX));
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000475 }
476}
477
Scroggo01b87ec2011-05-11 18:05:38 +0000478static const float ONE_OVER_255 = 1.f / 255.f;
479
480#define GR_COLOR_TO_VEC4(color) {\
481 GrColorUnpackR(color) * ONE_OVER_255,\
482 GrColorUnpackG(color) * ONE_OVER_255,\
483 GrColorUnpackB(color) * ONE_OVER_255,\
484 GrColorUnpackA(color) * ONE_OVER_255 \
485}
486
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000487void GrGpuGLShaders::flushColor() {
488 const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc();
489 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
490 // color will be specified per-vertex as an attribute
491 // invalidate the const vertex attrib color
492 fHWDrawState.fColor = GrColor_ILLEGAL;
493 } else {
494 switch (desc.fColorType) {
495 case GrGLProgram::ProgramDesc::kAttribute_ColorType:
496 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
497 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000498 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000499 GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000500 fHWDrawState.fColor = fCurrDrawState.fColor;
501 }
502 break;
503 case GrGLProgram::ProgramDesc::kUniform_ColorType:
504 if (fProgramData->fColor != fCurrDrawState.fColor) {
505 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000506 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000507 GrAssert(GrGLProgram::kUnusedUniform !=
508 fProgramData->fUniLocations.fColorUni);
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000509 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
510 fProgramData->fColor = fCurrDrawState.fColor;
511 }
512 break;
513 case GrGLProgram::ProgramDesc::kNone_ColorType:
514 GrAssert(0xffffffff == fCurrDrawState.fColor);
515 break;
516 default:
517 GrCrash("Unknown color type.");
518 }
519 }
Scroggo97c88c22011-05-11 14:05:25 +0000520 if (fProgramData->fUniLocations.fColorFilterUni
521 != GrGLProgram::kUnusedUniform
522 && fProgramData->fColorFilterColor
523 != fCurrDrawState.fColorFilterColor) {
Scroggo01b87ec2011-05-11 18:05:38 +0000524 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
Scroggo97c88c22011-05-11 14:05:25 +0000525 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
526 fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
527 }
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000528}
529
530
junov@google.comf93e7172011-03-31 21:26:24 +0000531bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
532 if (!flushGLStateCommon(type)) {
533 return false;
534 }
535
536 if (fDirtyFlags.fRenderTargetChanged) {
537 // our coords are in pixel space and the GL matrices map to NDC
538 // so if the viewport changed, our matrix is now wrong.
junov@google.comf93e7172011-03-31 21:26:24 +0000539 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
junov@google.comf93e7172011-03-31 21:26:24 +0000540 // we assume all shader matrices may be wrong after viewport changes
541 fProgramCache->invalidateViewMatrices();
junov@google.comf93e7172011-03-31 21:26:24 +0000542 }
543
junov@google.comf93e7172011-03-31 21:26:24 +0000544 buildProgram(type);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000545 fProgramData = fProgramCache->getProgramData(fCurrentProgram);
bsalomon@google.com91961302011-05-09 18:39:58 +0000546 if (NULL == fProgramData) {
547 GrAssert(!"Failed to create program!");
548 return false;
549 }
junov@google.comf93e7172011-03-31 21:26:24 +0000550
551 if (fHWProgramID != fProgramData->fProgramID) {
552 GR_GL(UseProgram(fProgramData->fProgramID));
553 fHWProgramID = fProgramData->fProgramID;
554 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000555 GrBlendCoeff srcCoeff = fCurrDrawState.fSrcBlend;
556 GrBlendCoeff dstCoeff = fCurrDrawState.fDstBlend;
557
558 fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
559 this->flushBlend(type, srcCoeff, dstCoeff);
junov@google.comf93e7172011-03-31 21:26:24 +0000560
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000561 this->flushColor();
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000562
bsalomon@google.com91961302011-05-09 18:39:58 +0000563 GrMatrix* currViewMatrix;
564 if (GrGLProgram::kSetAsAttribute ==
565 fProgramData->fUniLocations.fViewMatrixUni) {
566 currViewMatrix = &fHWDrawState.fViewMatrix;
567 } else {
568 currViewMatrix = &fProgramData->fViewMatrix;
569 }
junov@google.comf93e7172011-03-31 21:26:24 +0000570
bsalomon@google.com91961302011-05-09 18:39:58 +0000571 if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000572 flushViewMatrix();
bsalomon@google.com91961302011-05-09 18:39:58 +0000573 *currViewMatrix = fCurrDrawState.fViewMatrix;
junov@google.comf93e7172011-03-31 21:26:24 +0000574 }
575
576 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000577 this->flushTextureMatrix(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000578
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000579 this->flushRadial2(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000580
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000581 this->flushTexelSize(s);
junov@google.com6acc9b32011-05-16 18:32:07 +0000582
583 this->flushTextureDomain(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000584 }
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000585 this->flushEdgeAAData();
junov@google.comf93e7172011-03-31 21:26:24 +0000586 resetDirtyFlags();
587 return true;
588}
589
590void GrGpuGLShaders::postDraw() {
junov@google.comf93e7172011-03-31 21:26:24 +0000591}
592
593void GrGpuGLShaders::setupGeometry(int* startVertex,
594 int* startIndex,
595 int vertexCount,
596 int indexCount) {
597
598 int newColorOffset;
599 int newTexCoordOffsets[kMaxTexCoords];
600
601 GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
602 newTexCoordOffsets,
603 &newColorOffset);
604 int oldColorOffset;
605 int oldTexCoordOffsets[kMaxTexCoords];
606 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
607 oldTexCoordOffsets,
608 &oldColorOffset);
609 bool indexed = NULL != startIndex;
610
611 int extraVertexOffset;
612 int extraIndexOffset;
613 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
614
615 GrGLenum scalarType;
616 bool texCoordNorm;
617 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
618 scalarType = GrGLTextType;
619 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
620 } else {
621 scalarType = GrGLType;
622 texCoordNorm = false;
623 }
624
625 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
626 *startVertex = 0;
627 if (indexed) {
628 *startIndex += extraIndexOffset;
629 }
630
631 // all the Pointers must be set if any of these are true
632 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
633 vertexOffset != fHWGeometryState.fVertexOffset ||
634 newStride != oldStride;
635
636 // position and tex coord offsets change if above conditions are true
637 // or the type/normalization changed based on text vs nontext type coords.
638 bool posAndTexChange = allOffsetsChange ||
639 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
640 (kTextFormat_VertexLayoutBit &
641 (fHWGeometryState.fVertexLayout ^
642 fGeometrySrc.fVertexLayout)));
643
644 if (posAndTexChange) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000645 int idx = GrGLProgram::PositionAttributeIdx();
646 GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
647 (GrGLvoid*)vertexOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000648 fHWGeometryState.fVertexOffset = vertexOffset;
649 }
650
651 for (int t = 0; t < kMaxTexCoords; ++t) {
652 if (newTexCoordOffsets[t] > 0) {
653 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
bsalomon@google.com91961302011-05-09 18:39:58 +0000654 int idx = GrGLProgram::TexCoordAttributeIdx(t);
junov@google.comf93e7172011-03-31 21:26:24 +0000655 if (oldTexCoordOffsets[t] <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000656 GR_GL(EnableVertexAttribArray(idx));
657 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
658 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000659 } else if (posAndTexChange ||
660 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000661 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
662 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000663 }
664 } else if (oldTexCoordOffsets[t] > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000665 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000666 }
667 }
668
669 if (newColorOffset > 0) {
670 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
bsalomon@google.com91961302011-05-09 18:39:58 +0000671 int idx = GrGLProgram::ColorAttributeIdx();
junov@google.comf93e7172011-03-31 21:26:24 +0000672 if (oldColorOffset <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000673 GR_GL(EnableVertexAttribArray(idx));
674 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000675 true, newStride, colorOffset));
676 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000677 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000678 true, newStride, colorOffset));
679 }
680 } else if (oldColorOffset > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000681 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000682 }
683
684 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
685 fHWGeometryState.fArrayPtrsDirty = false;
686}
687
688void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000689 GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc;
junov@google.comf93e7172011-03-31 21:26:24 +0000690
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000691 // Must initialize all fields or cache will have false negatives!
692 desc.fVertexLayout = fGeometrySrc.fVertexLayout;
693
694 desc.fEmitsPointSize = kPoints_PrimitiveType == type;
695
696 bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
697 // fColorType records how colors are specified for the program. Strip
698 // the bit from the layout to avoid false negatives when searching for an
699 // existing program in the cache.
700 desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
701
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000702 desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
703
junov@google.comf93e7172011-03-31 21:26:24 +0000704#if GR_AGGRESSIVE_SHADER_OPTS
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000705 if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
junov@google.comc97db4c2011-04-29 17:25:42 +0000706 desc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000707 } else
junov@google.comf93e7172011-03-31 21:26:24 +0000708#endif
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000709#if GR_GL_NO_CONSTANT_ATTRIBUTES
710 if (!requiresAttributeColors) {
711 desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
712 } else
713#endif
714 {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000715 if (requiresAttributeColors) {} // suppress unused var warning
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000716 desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
717 }
junov@google.comf93e7172011-03-31 21:26:24 +0000718
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000719 desc.fEdgeAANumEdges = fCurrDrawState.fEdgeAANumEdges;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000720
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000721 int lastEnabledStage = -1;
722
junov@google.comf93e7172011-03-31 21:26:24 +0000723 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000724 GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000725
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000726 stage.fEnabled = this->isStageEnabled(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000727
728 if (stage.fEnabled) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000729 lastEnabledStage = s;
junov@google.comf93e7172011-03-31 21:26:24 +0000730 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
731 GrAssert(NULL != texture);
732 // we matrix to invert when orientation is TopDown, so make sure
733 // we aren't in that case before flagging as identity.
734 if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
735 stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit;
736 } else if (!getSamplerMatrix(s).hasPerspective()) {
737 stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit;
738 } else {
739 stage.fOptFlags = 0;
740 }
741 switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000742 case GrSamplerState::kNormal_SampleMode:
743 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping;
744 break;
745 case GrSamplerState::kRadial_SampleMode:
746 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping;
747 break;
748 case GrSamplerState::kRadial2_SampleMode:
749 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping;
750 break;
751 case GrSamplerState::kSweep_SampleMode:
752 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping;
753 break;
754 default:
755 GrCrash("Unexpected sample mode!");
756 break;
757 }
758
759 switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
760 // these both can use a regular texture2D()
761 case GrSamplerState::kNearest_Filter:
762 case GrSamplerState::kBilinear_Filter:
763 stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode;
764 break;
765 // performs 4 texture2D()s
766 case GrSamplerState::k4x4Downsample_Filter:
767 stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode;
768 break;
769 default:
770 GrCrash("Unexpected filter!");
771 break;
junov@google.comf93e7172011-03-31 21:26:24 +0000772 }
773
junov@google.com6acc9b32011-05-16 18:32:07 +0000774 if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
775 GrAssert(GrSamplerState::kClamp_WrapMode ==
776 fCurrDrawState.fSamplerStates[s].getWrapX() &&
777 GrSamplerState::kClamp_WrapMode ==
778 fCurrDrawState.fSamplerStates[s].getWrapY());
779 stage.fOptFlags |=
780 GrGLProgram::ProgramDesc::StageDesc::
781 kCustomTextureDomain_OptFlagBit;
782 }
783
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000784 if (GrPixelConfigIsAlphaOnly(texture->config())) {
junov@google.comf93e7172011-03-31 21:26:24 +0000785 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation;
786 } else {
787 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation;
788 }
junov@google.comf93e7172011-03-31 21:26:24 +0000789 } else {
790 stage.fOptFlags = 0;
791 stage.fCoordMapping = (GrGLProgram::ProgramDesc::StageDesc::CoordMapping)0;
792 stage.fModulation = (GrGLProgram::ProgramDesc::StageDesc::Modulation)0;
junov@google.comf93e7172011-03-31 21:26:24 +0000793 }
794 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000795
796 desc.fDualSrcOutput = GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
797 // use canonical value when coverage/color distinction won't affect
798 // generated code to prevent duplicate programs.
799 desc.fFirstCoverageStage = kNumStages;
800 if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
801 // color filter is applied between color/coverage computation
802 if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
803 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
804 }
805
806 // We could consider cases where the final color is solid (0xff alpha)
807 // and the dst coeff can correctly be set to a non-dualsrc gl value.
808 // (e.g. solid draw, and dst coeff is kZero. It's correct to make
809 // the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
810 // kOne).
811 if (fDualSourceBlendingSupport) {
812 if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
813 // write the coverage value to second color
814 desc.fDualSrcOutput =
815 GrGLProgram::ProgramDesc::kCoverage_DualSrcOutput;
816 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
817 } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
818 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
819 // cover
820 desc.fDualSrcOutput =
821 GrGLProgram::ProgramDesc::kCoverageISA_DualSrcOutput;
822 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
823 } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
824 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
825 // cover
826 desc.fDualSrcOutput =
827 GrGLProgram::ProgramDesc::kCoverageISC_DualSrcOutput;
828 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
829 }
830 }
831 }
junov@google.comf93e7172011-03-31 21:26:24 +0000832}
833
834