blob: 0a933b5268b1ef5362e4cec23d6ea4b293812b2a [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
junov@google.com53a55842011-06-08 22:55:10 +0000133void GrGpuGLShaders::abandonResources(){
134 INHERITED::abandonResources();
135 fProgramCache->abandon();
136}
137
junov@google.comf93e7172011-03-31 21:26:24 +0000138void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) {
139 GR_GL(DeleteShader(programData->fVShaderID));
140 GR_GL(DeleteShader(programData->fFShaderID));
141 GR_GL(DeleteProgram(programData->fProgramID));
142 GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));)
143}
144
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000145void GrGpuGLShaders::ProgramUnitTest() {
146
147 static const int STAGE_OPTS[] = {
148 0,
149 GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit,
150 GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping
151 };
152 static const GrGLProgram::ProgramDesc::StageDesc::Modulation STAGE_MODULATES[] = {
153 GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation,
154 GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation
155 };
156 static const GrGLProgram::ProgramDesc::StageDesc::CoordMapping STAGE_COORD_MAPPINGS[] = {
157 GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping,
158 GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping,
159 GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping,
160 GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping
161 };
162 static const GrGLProgram::ProgramDesc::StageDesc::FetchMode FETCH_MODES[] = {
163 GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode,
164 GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode,
165 };
166 GrGLProgram program;
167 GrGLProgram::ProgramDesc& pdesc = program.fProgramDesc;
168
169 static const int NUM_TESTS = 512;
170
171 // GrRandoms nextU() values have patterns in the low bits
172 // So using nextU() % array_count might never take some values.
173 GrRandom random;
174 for (int t = 0; t < NUM_TESTS; ++t) {
175
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000176#if 0
177 GrPrintf("\nTest Program %d\n-------------\n", t);
178 static const int stop = -1;
179 if (t == stop) {
180 int breakpointhere = 9;
181 }
182#endif
183
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000184 pdesc.fVertexLayout = 0;
185 pdesc.fEmitsPointSize = random.nextF() > .5f;
186 float colorType = random.nextF();
187 if (colorType < 1.f / 3.f) {
188 pdesc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
189 } else if (colorType < 2.f / 3.f) {
190 pdesc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
191 } else {
192 pdesc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
193 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000194
195 int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt));
196 pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx;
197
198 idx = (int)(random.nextF() * (kNumStages+1));
199 pdesc.fFirstCoverageStage = idx;
200
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000201 pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1));
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000202
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000203 if (fDualSourceBlendingSupport) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000204 pdesc.fDualSrcOutput =
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000205 (GrGLProgram::ProgramDesc::DualSrcOutput)
206 (int)(random.nextF() * GrGLProgram::ProgramDesc::kDualSrcOutputCnt);
207 } else {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000208 pdesc.fDualSrcOutput =
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000209 GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
210 }
211
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000212 for (int s = 0; s < kNumStages; ++s) {
213 // enable the stage?
214 if (random.nextF() > .5f) {
215 // use separate tex coords?
216 if (random.nextF() > .5f) {
217 int t = (int)(random.nextF() * kMaxTexCoords);
218 pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
219 } else {
220 pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
221 }
222 }
223 // use text-formatted verts?
224 if (random.nextF() > .5f) {
225 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
226 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000227 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
228 pdesc.fStages[s].fOptFlags = STAGE_OPTS[idx];
229 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
230 pdesc.fStages[s].fModulation = STAGE_MODULATES[idx];
231 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
232 pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[idx];
233 idx = (int)(random.nextF() * GR_ARRAY_COUNT(FETCH_MODES));
234 pdesc.fStages[s].fFetchMode = FETCH_MODES[idx];
tomhudson@google.com0d831722011-06-02 15:37:14 +0000235 pdesc.fStages[s].setEnabled(VertexUsesStage(s, pdesc.fVertexLayout));
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000236 }
237 GrGLProgram::CachedData cachedData;
238 program.genProgram(&cachedData);
239 DeleteProgram(&cachedData);
240 bool again = false;
241 if (again) {
242 program.genProgram(&cachedData);
243 DeleteProgram(&cachedData);
244 }
245 }
246}
247
junov@google.comf93e7172011-03-31 21:26:24 +0000248GrGpuGLShaders::GrGpuGLShaders() {
249
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000250 resetContext();
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000251 int major, minor;
252 gl_version(&major, &minor);
253
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000254 f4X4DownsampleFilterSupport = true;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000255 if (GR_GL_SUPPORT_DESKTOP) {
256 fDualSourceBlendingSupport =
257 major > 3 ||(3 == major && 3 <= minor) ||
258 has_gl_extension("GL_ARB_blend_func_extended");
259 } else {
260 fDualSourceBlendingSupport = false;
261 }
junov@google.comf93e7172011-03-31 21:26:24 +0000262
263 fProgramData = NULL;
264 fProgramCache = new ProgramCache();
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000265
266#if 0
267 ProgramUnitTest();
268#endif
junov@google.comf93e7172011-03-31 21:26:24 +0000269}
270
271GrGpuGLShaders::~GrGpuGLShaders() {
272 delete fProgramCache;
273}
274
275const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
junov@google.comf93e7172011-03-31 21:26:24 +0000276 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000277
278 if (GrGLProgram::kSetAsAttribute ==
279 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
280 return fHWDrawState.fSamplerStates[stage].getMatrix();
281 } else {
282 return fProgramData->fTextureMatrices[stage];
283 }
junov@google.comf93e7172011-03-31 21:26:24 +0000284}
285
286void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000287 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000288 if (GrGLProgram::kSetAsAttribute ==
289 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
290 fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
291 } else {
292 fProgramData->fTextureMatrices[stage] = matrix;
293 }
junov@google.comf93e7172011-03-31 21:26:24 +0000294}
295
296void GrGpuGLShaders::resetContext() {
297 INHERITED::resetContext();
junov@google.comf93e7172011-03-31 21:26:24 +0000298
junov@google.comf93e7172011-03-31 21:26:24 +0000299 fHWGeometryState.fVertexLayout = 0;
300 fHWGeometryState.fVertexOffset = ~0;
bsalomon@google.com91961302011-05-09 18:39:58 +0000301 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000302 for (int t = 0; t < kMaxTexCoords; ++t) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000303 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000304 }
bsalomon@google.com91961302011-05-09 18:39:58 +0000305 GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000306
307 fHWProgramID = 0;
308}
309
310void GrGpuGLShaders::flushViewMatrix() {
311 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.comcc4dac32011-05-10 13:52:42 +0000312 GrMatrix m;
313 m.setAll(
junov@google.comf93e7172011-03-31 21:26:24 +0000314 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
315 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
316 0, 0, GrMatrix::I()[8]);
317 m.setConcat(m, fCurrDrawState.fViewMatrix);
318
319 // ES doesn't allow you to pass true to the transpose param,
320 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000321 GrGLfloat mt[] = {
322 GrScalarToFloat(m[GrMatrix::kMScaleX]),
323 GrScalarToFloat(m[GrMatrix::kMSkewY]),
324 GrScalarToFloat(m[GrMatrix::kMPersp0]),
325 GrScalarToFloat(m[GrMatrix::kMSkewX]),
326 GrScalarToFloat(m[GrMatrix::kMScaleY]),
327 GrScalarToFloat(m[GrMatrix::kMPersp1]),
328 GrScalarToFloat(m[GrMatrix::kMTransX]),
329 GrScalarToFloat(m[GrMatrix::kMTransY]),
330 GrScalarToFloat(m[GrMatrix::kMPersp2])
junov@google.comf93e7172011-03-31 21:26:24 +0000331 };
bsalomon@google.com91961302011-05-09 18:39:58 +0000332
333 if (GrGLProgram::kSetAsAttribute ==
334 fProgramData->fUniLocations.fViewMatrixUni) {
335 int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
336 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
337 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
338 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
339 } else {
340 GrAssert(GrGLProgram::kUnusedUniform !=
341 fProgramData->fUniLocations.fViewMatrixUni);
342 GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
343 1, false, mt));
344 }
junov@google.comf93e7172011-03-31 21:26:24 +0000345}
346
junov@google.com6acc9b32011-05-16 18:32:07 +0000347void GrGpuGLShaders::flushTextureDomain(int s) {
348 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
349 if (GrGLProgram::kUnusedUniform != uni) {
twiz@google.com76b82742011-06-02 20:30:02 +0000350 const GrRect &texDom =
junov@google.com6acc9b32011-05-16 18:32:07 +0000351 fCurrDrawState.fSamplerStates[s].getTextureDomain();
352
twiz@google.com76b82742011-06-02 20:30:02 +0000353 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
354 fProgramData->fTextureDomain[s] != texDom) {
junov@google.com6acc9b32011-05-16 18:32:07 +0000355
junov@google.com2f839402011-05-24 15:13:01 +0000356 fProgramData->fTextureDomain[s] = texDom;
junov@google.com6acc9b32011-05-16 18:32:07 +0000357
junov@google.com2f839402011-05-24 15:13:01 +0000358 float values[4] = {
twiz@google.com76b82742011-06-02 20:30:02 +0000359 GrScalarToFloat(texDom.left()),
360 GrScalarToFloat(texDom.top()),
361 GrScalarToFloat(texDom.right()),
362 GrScalarToFloat(texDom.bottom())
junov@google.com2f839402011-05-24 15:13:01 +0000363 };
364
365 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
366 GrGLTexture::Orientation orientation = texture->orientation();
367
368 // vertical flip if necessary
369 if (GrGLTexture::kBottomUp_Orientation == orientation) {
370 values[1] = 1.0f - values[1];
371 values[3] = 1.0f - values[3];
twiz@google.com76b82742011-06-02 20:30:02 +0000372 // The top and bottom were just flipped, so correct the ordering
373 // of elements so that values = (l, t, r, b).
374 SkTSwap(values[1], values[3]);
junov@google.com2f839402011-05-24 15:13:01 +0000375 }
376
377 values[0] *= SkScalarToFloat(texture->contentScaleX());
378 values[2] *= SkScalarToFloat(texture->contentScaleX());
379 values[1] *= SkScalarToFloat(texture->contentScaleY());
380 values[3] *= SkScalarToFloat(texture->contentScaleY());
381
382 GR_GL(Uniform4fv(uni, 1, values));
junov@google.com6acc9b32011-05-16 18:32:07 +0000383 }
junov@google.com6acc9b32011-05-16 18:32:07 +0000384 }
385}
386
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000387void GrGpuGLShaders::flushTextureMatrix(int s) {
junov@google.com6acc9b32011-05-16 18:32:07 +0000388 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000389 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
390 if (NULL != texture) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000391 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000392 (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
393 getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
junov@google.comf93e7172011-03-31 21:26:24 +0000394
bsalomon@google.com91961302011-05-09 18:39:58 +0000395 GrAssert(NULL != fCurrDrawState.fTextures[s]);
junov@google.comf93e7172011-03-31 21:26:24 +0000396
bsalomon@google.com91961302011-05-09 18:39:58 +0000397 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000398
bsalomon@google.com91961302011-05-09 18:39:58 +0000399 GrMatrix m = getSamplerMatrix(s);
400 GrSamplerState::SampleMode mode =
401 fCurrDrawState.fSamplerStates[s].getSampleMode();
402 AdjustTextureMatrix(texture, mode, &m);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000403
bsalomon@google.com91961302011-05-09 18:39:58 +0000404 // ES doesn't allow you to pass true to the transpose param,
405 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000406 GrGLfloat mt[] = {
407 GrScalarToFloat(m[GrMatrix::kMScaleX]),
408 GrScalarToFloat(m[GrMatrix::kMSkewY]),
409 GrScalarToFloat(m[GrMatrix::kMPersp0]),
410 GrScalarToFloat(m[GrMatrix::kMSkewX]),
411 GrScalarToFloat(m[GrMatrix::kMScaleY]),
412 GrScalarToFloat(m[GrMatrix::kMPersp1]),
413 GrScalarToFloat(m[GrMatrix::kMTransX]),
414 GrScalarToFloat(m[GrMatrix::kMTransY]),
415 GrScalarToFloat(m[GrMatrix::kMPersp2])
bsalomon@google.com91961302011-05-09 18:39:58 +0000416 };
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000417
bsalomon@google.com91961302011-05-09 18:39:58 +0000418 if (GrGLProgram::kSetAsAttribute ==
419 fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
420 int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s);
421 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
422 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
423 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
424 } else {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000425 GR_GL(UniformMatrix3fv(uni, 1, false, mt));
bsalomon@google.com91961302011-05-09 18:39:58 +0000426 }
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000427 recordHWSamplerMatrix(s, getSamplerMatrix(s));
428 }
429 }
junov@google.comf93e7172011-03-31 21:26:24 +0000430}
431
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000432void GrGpuGLShaders::flushRadial2(int s) {
junov@google.comf93e7172011-03-31 21:26:24 +0000433
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000434 const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
435 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com91961302011-05-09 18:39:58 +0000436 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000437 (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
438 fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
439 fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
junov@google.comf93e7172011-03-31 21:26:24 +0000440
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000441 GrScalar centerX1 = sampler.getRadial2CenterX1();
442 GrScalar radius0 = sampler.getRadial2Radius0();
junov@google.comf93e7172011-03-31 21:26:24 +0000443
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000444 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
junov@google.comf93e7172011-03-31 21:26:24 +0000445
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000446 float values[6] = {
447 GrScalarToFloat(a),
448 1 / (2.f * values[0]),
449 GrScalarToFloat(centerX1),
450 GrScalarToFloat(radius0),
451 GrScalarToFloat(GrMul(radius0, radius0)),
452 sampler.isRadial2PosRoot() ? 1.f : -1.f
453 };
454 GR_GL(Uniform1fv(uni, 6, values));
455 fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
456 fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0();
457 fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
458 }
459}
460
461void GrGpuGLShaders::flushTexelSize(int s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000462 const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
bsalomon@google.com91961302011-05-09 18:39:58 +0000463 if (GrGLProgram::kUnusedUniform != uni) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000464 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
465 if (texture->allocWidth() != fProgramData->fTextureWidth[s] ||
466 texture->allocHeight() != fProgramData->fTextureWidth[s]) {
467
468 float texelSize[] = {1.f / texture->allocWidth(),
469 1.f / texture->allocHeight()};
470 GR_GL(Uniform2fv(uni, 1, texelSize));
471 }
472 }
junov@google.comf93e7172011-03-31 21:26:24 +0000473}
474
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000475void GrGpuGLShaders::flushEdgeAAData() {
476 const int& uni = fProgramData->fUniLocations.fEdgesUni;
477 if (GrGLProgram::kUnusedUniform != uni) {
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000478 int count = fCurrDrawState.fEdgeAANumEdges;
479 Edge edges[kMaxEdges];
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000480 // Flip the edges in Y
481 float height = fCurrDrawState.fRenderTarget->height();
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000482 for (int i = 0; i < count; ++i) {
483 edges[i] = fCurrDrawState.fEdgeAAEdges[i];
484 float b = edges[i].fY;
485 edges[i].fY = -b;
486 edges[i].fZ += b * height;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000487 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000488 GR_GL(Uniform3fv(uni, count, &edges[0].fX));
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000489 }
490}
491
Scroggo01b87ec2011-05-11 18:05:38 +0000492static const float ONE_OVER_255 = 1.f / 255.f;
493
494#define GR_COLOR_TO_VEC4(color) {\
495 GrColorUnpackR(color) * ONE_OVER_255,\
496 GrColorUnpackG(color) * ONE_OVER_255,\
497 GrColorUnpackB(color) * ONE_OVER_255,\
498 GrColorUnpackA(color) * ONE_OVER_255 \
499}
500
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000501void GrGpuGLShaders::flushColor() {
502 const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc();
503 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
504 // color will be specified per-vertex as an attribute
505 // invalidate the const vertex attrib color
506 fHWDrawState.fColor = GrColor_ILLEGAL;
507 } else {
508 switch (desc.fColorType) {
509 case GrGLProgram::ProgramDesc::kAttribute_ColorType:
510 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
511 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000512 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000513 GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000514 fHWDrawState.fColor = fCurrDrawState.fColor;
515 }
516 break;
517 case GrGLProgram::ProgramDesc::kUniform_ColorType:
518 if (fProgramData->fColor != fCurrDrawState.fColor) {
519 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000520 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000521 GrAssert(GrGLProgram::kUnusedUniform !=
522 fProgramData->fUniLocations.fColorUni);
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000523 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
524 fProgramData->fColor = fCurrDrawState.fColor;
525 }
526 break;
527 case GrGLProgram::ProgramDesc::kNone_ColorType:
528 GrAssert(0xffffffff == fCurrDrawState.fColor);
529 break;
530 default:
531 GrCrash("Unknown color type.");
532 }
533 }
Scroggo97c88c22011-05-11 14:05:25 +0000534 if (fProgramData->fUniLocations.fColorFilterUni
535 != GrGLProgram::kUnusedUniform
536 && fProgramData->fColorFilterColor
537 != fCurrDrawState.fColorFilterColor) {
Scroggo01b87ec2011-05-11 18:05:38 +0000538 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
Scroggo97c88c22011-05-11 14:05:25 +0000539 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
540 fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
541 }
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000542}
543
544
junov@google.comf93e7172011-03-31 21:26:24 +0000545bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
546 if (!flushGLStateCommon(type)) {
547 return false;
548 }
549
550 if (fDirtyFlags.fRenderTargetChanged) {
551 // our coords are in pixel space and the GL matrices map to NDC
552 // so if the viewport changed, our matrix is now wrong.
junov@google.comf93e7172011-03-31 21:26:24 +0000553 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
junov@google.comf93e7172011-03-31 21:26:24 +0000554 // we assume all shader matrices may be wrong after viewport changes
555 fProgramCache->invalidateViewMatrices();
junov@google.comf93e7172011-03-31 21:26:24 +0000556 }
557
junov@google.comf93e7172011-03-31 21:26:24 +0000558 buildProgram(type);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000559 fProgramData = fProgramCache->getProgramData(fCurrentProgram);
bsalomon@google.com91961302011-05-09 18:39:58 +0000560 if (NULL == fProgramData) {
561 GrAssert(!"Failed to create program!");
562 return false;
563 }
junov@google.comf93e7172011-03-31 21:26:24 +0000564
565 if (fHWProgramID != fProgramData->fProgramID) {
566 GR_GL(UseProgram(fProgramData->fProgramID));
567 fHWProgramID = fProgramData->fProgramID;
568 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000569 GrBlendCoeff srcCoeff = fCurrDrawState.fSrcBlend;
570 GrBlendCoeff dstCoeff = fCurrDrawState.fDstBlend;
571
572 fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
573 this->flushBlend(type, srcCoeff, dstCoeff);
junov@google.comf93e7172011-03-31 21:26:24 +0000574
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000575 this->flushColor();
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000576
bsalomon@google.com91961302011-05-09 18:39:58 +0000577 GrMatrix* currViewMatrix;
578 if (GrGLProgram::kSetAsAttribute ==
579 fProgramData->fUniLocations.fViewMatrixUni) {
580 currViewMatrix = &fHWDrawState.fViewMatrix;
581 } else {
582 currViewMatrix = &fProgramData->fViewMatrix;
583 }
junov@google.comf93e7172011-03-31 21:26:24 +0000584
bsalomon@google.com91961302011-05-09 18:39:58 +0000585 if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000586 flushViewMatrix();
bsalomon@google.com91961302011-05-09 18:39:58 +0000587 *currViewMatrix = fCurrDrawState.fViewMatrix;
junov@google.comf93e7172011-03-31 21:26:24 +0000588 }
589
590 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000591 this->flushTextureMatrix(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000592
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000593 this->flushRadial2(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000594
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000595 this->flushTexelSize(s);
junov@google.com6acc9b32011-05-16 18:32:07 +0000596
597 this->flushTextureDomain(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000598 }
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000599 this->flushEdgeAAData();
junov@google.comf93e7172011-03-31 21:26:24 +0000600 resetDirtyFlags();
601 return true;
602}
603
604void GrGpuGLShaders::postDraw() {
junov@google.comf93e7172011-03-31 21:26:24 +0000605}
606
607void GrGpuGLShaders::setupGeometry(int* startVertex,
608 int* startIndex,
609 int vertexCount,
610 int indexCount) {
611
612 int newColorOffset;
613 int newTexCoordOffsets[kMaxTexCoords];
614
615 GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
616 newTexCoordOffsets,
617 &newColorOffset);
618 int oldColorOffset;
619 int oldTexCoordOffsets[kMaxTexCoords];
620 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
621 oldTexCoordOffsets,
622 &oldColorOffset);
623 bool indexed = NULL != startIndex;
624
625 int extraVertexOffset;
626 int extraIndexOffset;
627 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
628
629 GrGLenum scalarType;
630 bool texCoordNorm;
631 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
632 scalarType = GrGLTextType;
633 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
634 } else {
635 scalarType = GrGLType;
636 texCoordNorm = false;
637 }
638
639 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
640 *startVertex = 0;
641 if (indexed) {
642 *startIndex += extraIndexOffset;
643 }
644
645 // all the Pointers must be set if any of these are true
646 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
647 vertexOffset != fHWGeometryState.fVertexOffset ||
648 newStride != oldStride;
649
650 // position and tex coord offsets change if above conditions are true
651 // or the type/normalization changed based on text vs nontext type coords.
652 bool posAndTexChange = allOffsetsChange ||
653 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
654 (kTextFormat_VertexLayoutBit &
655 (fHWGeometryState.fVertexLayout ^
656 fGeometrySrc.fVertexLayout)));
657
658 if (posAndTexChange) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000659 int idx = GrGLProgram::PositionAttributeIdx();
660 GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
661 (GrGLvoid*)vertexOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000662 fHWGeometryState.fVertexOffset = vertexOffset;
663 }
664
665 for (int t = 0; t < kMaxTexCoords; ++t) {
666 if (newTexCoordOffsets[t] > 0) {
667 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
bsalomon@google.com91961302011-05-09 18:39:58 +0000668 int idx = GrGLProgram::TexCoordAttributeIdx(t);
junov@google.comf93e7172011-03-31 21:26:24 +0000669 if (oldTexCoordOffsets[t] <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000670 GR_GL(EnableVertexAttribArray(idx));
671 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
672 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000673 } else if (posAndTexChange ||
674 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000675 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
676 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000677 }
678 } else if (oldTexCoordOffsets[t] > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000679 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000680 }
681 }
682
683 if (newColorOffset > 0) {
684 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
bsalomon@google.com91961302011-05-09 18:39:58 +0000685 int idx = GrGLProgram::ColorAttributeIdx();
junov@google.comf93e7172011-03-31 21:26:24 +0000686 if (oldColorOffset <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000687 GR_GL(EnableVertexAttribArray(idx));
688 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000689 true, newStride, colorOffset));
690 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000691 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000692 true, newStride, colorOffset));
693 }
694 } else if (oldColorOffset > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000695 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000696 }
697
698 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
699 fHWGeometryState.fArrayPtrsDirty = false;
700}
701
702void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000703 GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc;
junov@google.comf93e7172011-03-31 21:26:24 +0000704
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000705 // Must initialize all fields or cache will have false negatives!
706 desc.fVertexLayout = fGeometrySrc.fVertexLayout;
707
708 desc.fEmitsPointSize = kPoints_PrimitiveType == type;
709
710 bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
711 // fColorType records how colors are specified for the program. Strip
712 // the bit from the layout to avoid false negatives when searching for an
713 // existing program in the cache.
714 desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
715
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000716 desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
717
junov@google.comf93e7172011-03-31 21:26:24 +0000718#if GR_AGGRESSIVE_SHADER_OPTS
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000719 if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
junov@google.comc97db4c2011-04-29 17:25:42 +0000720 desc.fColorType = GrGLProgram::ProgramDesc::kNone_ColorType;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000721 } else
junov@google.comf93e7172011-03-31 21:26:24 +0000722#endif
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000723#if GR_GL_NO_CONSTANT_ATTRIBUTES
724 if (!requiresAttributeColors) {
725 desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
726 } else
727#endif
728 {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000729 if (requiresAttributeColors) {} // suppress unused var warning
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000730 desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
731 }
junov@google.comf93e7172011-03-31 21:26:24 +0000732
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000733 desc.fEdgeAANumEdges = fCurrDrawState.fEdgeAANumEdges;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000734
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000735 int lastEnabledStage = -1;
736
junov@google.comf93e7172011-03-31 21:26:24 +0000737 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000738 GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000739
tomhudson@google.com0d831722011-06-02 15:37:14 +0000740 stage.fOptFlags = 0;
741 stage.setEnabled(this->isStageEnabled(s));
junov@google.comf93e7172011-03-31 21:26:24 +0000742
tomhudson@google.com0d831722011-06-02 15:37:14 +0000743 if (stage.isEnabled()) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000744 lastEnabledStage = s;
junov@google.comf93e7172011-03-31 21:26:24 +0000745 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
746 GrAssert(NULL != texture);
747 // we matrix to invert when orientation is TopDown, so make sure
748 // we aren't in that case before flagging as identity.
749 if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000750 stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit;
junov@google.comf93e7172011-03-31 21:26:24 +0000751 } else if (!getSamplerMatrix(s).hasPerspective()) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000752 stage.fOptFlags |= GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit;
junov@google.comf93e7172011-03-31 21:26:24 +0000753 }
754 switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000755 case GrSamplerState::kNormal_SampleMode:
756 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping;
757 break;
758 case GrSamplerState::kRadial_SampleMode:
759 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping;
760 break;
761 case GrSamplerState::kRadial2_SampleMode:
762 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping;
763 break;
764 case GrSamplerState::kSweep_SampleMode:
765 stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping;
766 break;
767 default:
768 GrCrash("Unexpected sample mode!");
769 break;
770 }
771
772 switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
773 // these both can use a regular texture2D()
774 case GrSamplerState::kNearest_Filter:
775 case GrSamplerState::kBilinear_Filter:
776 stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::kSingle_FetchMode;
777 break;
778 // performs 4 texture2D()s
779 case GrSamplerState::k4x4Downsample_Filter:
780 stage.fFetchMode = GrGLProgram::ProgramDesc::StageDesc::k2x2_FetchMode;
781 break;
782 default:
783 GrCrash("Unexpected filter!");
784 break;
junov@google.comf93e7172011-03-31 21:26:24 +0000785 }
786
junov@google.com6acc9b32011-05-16 18:32:07 +0000787 if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000788 GrAssert(GrSamplerState::kClamp_WrapMode ==
789 fCurrDrawState.fSamplerStates[s].getWrapX() &&
junov@google.com6acc9b32011-05-16 18:32:07 +0000790 GrSamplerState::kClamp_WrapMode ==
791 fCurrDrawState.fSamplerStates[s].getWrapY());
tomhudson@google.com0d831722011-06-02 15:37:14 +0000792 stage.fOptFlags |=
junov@google.com6acc9b32011-05-16 18:32:07 +0000793 GrGLProgram::ProgramDesc::StageDesc::
794 kCustomTextureDomain_OptFlagBit;
795 }
796
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000797 if (GrPixelConfigIsAlphaOnly(texture->config())) {
junov@google.comf93e7172011-03-31 21:26:24 +0000798 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation;
799 } else {
800 stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation;
801 }
junov@google.comf93e7172011-03-31 21:26:24 +0000802 } else {
803 stage.fOptFlags = 0;
804 stage.fCoordMapping = (GrGLProgram::ProgramDesc::StageDesc::CoordMapping)0;
805 stage.fModulation = (GrGLProgram::ProgramDesc::StageDesc::Modulation)0;
junov@google.comf93e7172011-03-31 21:26:24 +0000806 }
807 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000808
809 desc.fDualSrcOutput = GrGLProgram::ProgramDesc::kNone_DualSrcOutput;
810 // use canonical value when coverage/color distinction won't affect
811 // generated code to prevent duplicate programs.
812 desc.fFirstCoverageStage = kNumStages;
813 if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
814 // color filter is applied between color/coverage computation
815 if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
816 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
817 }
818
819 // We could consider cases where the final color is solid (0xff alpha)
820 // and the dst coeff can correctly be set to a non-dualsrc gl value.
821 // (e.g. solid draw, and dst coeff is kZero. It's correct to make
822 // the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
823 // kOne).
824 if (fDualSourceBlendingSupport) {
825 if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
826 // write the coverage value to second color
827 desc.fDualSrcOutput =
828 GrGLProgram::ProgramDesc::kCoverage_DualSrcOutput;
829 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
830 } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
831 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
832 // cover
833 desc.fDualSrcOutput =
834 GrGLProgram::ProgramDesc::kCoverageISA_DualSrcOutput;
835 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
836 } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
837 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
838 // cover
839 desc.fDualSrcOutput =
840 GrGLProgram::ProgramDesc::kCoverageISC_DualSrcOutput;
841 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
842 }
843 }
844 }
junov@google.comf93e7172011-03-31 21:26:24 +0000845}