blob: 2de995081a0db046198dd19236f26bfcbccb53c8 [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"
junov@google.comf93e7172011-03-31 21:26:24 +000021#include "GrNoncopyable.h"
22#include "GrStringBuilder.h"
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000023#include "GrRandom.h"
junov@google.comf93e7172011-03-31 21:26:24 +000024
junov@google.comf93e7172011-03-31 21:26:24 +000025#define SKIP_CACHE_CHECK true
26#define GR_UINT32_MAX static_cast<uint32_t>(-1)
27
junov@google.comf93e7172011-03-31 21:26:24 +000028#include "GrTHashCache.h"
29
30class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable {
31private:
32 class Entry;
33
34#if GR_DEBUG
35 typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug
36#else
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +000037 typedef GrBinHashKey<Entry, 64> ProgramHashKey;
junov@google.comf93e7172011-03-31 21:26:24 +000038#endif
39
40 class Entry : public ::GrNoncopyable {
41 public:
42 Entry() {}
junov@google.comf93e7172011-03-31 21:26:24 +000043 void copyAndTakeOwnership(Entry& entry) {
44 fProgramData.copyAndTakeOwnership(entry.fProgramData);
45 fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000046 fLRUStamp = entry.fLRUStamp;
junov@google.comf93e7172011-03-31 21:26:24 +000047 }
48
49 public:
50 int compare(const ProgramHashKey& key) const { return fKey.compare(key); }
51
52 public:
53 GrGLProgram::CachedData fProgramData;
54 ProgramHashKey fKey;
55 unsigned int fLRUStamp;
56 };
57
58 GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
59
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000060 // We may have kMaxEntries+1 shaders in the GL context because
61 // we create a new shader before evicting from the cache.
junov@google.comf93e7172011-03-31 21:26:24 +000062 enum {
63 kMaxEntries = 32
64 };
65 Entry fEntries[kMaxEntries];
66 int fCount;
67 unsigned int fCurrLRUStamp;
68
69public:
70 ProgramCache()
71 : fCount(0)
72 , fCurrLRUStamp(0) {
73 }
74
75 ~ProgramCache() {
76 for (int i = 0; i < fCount; ++i) {
77 GrGpuGLShaders::DeleteProgram(&fEntries[i].fProgramData);
78 }
79 }
80
81 void abandon() {
82 fCount = 0;
83 }
84
85 void invalidateViewMatrices() {
86 for (int i = 0; i < fCount; ++i) {
87 // set to illegal matrix
88 fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix();
89 }
90 }
91
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000092 GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000093 Entry newEntry;
94 while (newEntry.fKey.doPass()) {
95 desc.buildKey(newEntry.fKey);
junov@google.comf93e7172011-03-31 21:26:24 +000096 }
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000097 Entry* entry = fHashCache.find(newEntry.fKey);
junov@google.comf93e7172011-03-31 21:26:24 +000098 if (NULL == entry) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +000099 if (!desc.genProgram(&newEntry.fProgramData)) {
100 return NULL;
101 }
junov@google.comf93e7172011-03-31 21:26:24 +0000102 if (fCount < kMaxEntries) {
103 entry = fEntries + fCount;
104 ++fCount;
105 } else {
106 GrAssert(kMaxEntries == fCount);
107 entry = fEntries;
108 for (int i = 1; i < kMaxEntries; ++i) {
109 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
110 entry = fEntries + i;
111 }
112 }
113 fHashCache.remove(entry->fKey, entry);
114 GrGpuGLShaders::DeleteProgram(&entry->fProgramData);
115 }
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +0000116 entry->copyAndTakeOwnership(newEntry);
junov@google.comf93e7172011-03-31 21:26:24 +0000117 fHashCache.insert(entry->fKey, entry);
118 }
119
120 entry->fLRUStamp = fCurrLRUStamp;
121 if (GR_UINT32_MAX == fCurrLRUStamp) {
122 // wrap around! just trash our LRU, one time hit.
123 for (int i = 0; i < fCount; ++i) {
124 fEntries[i].fLRUStamp = 0;
125 }
126 }
127 ++fCurrLRUStamp;
128 return &entry->fProgramData;
129 }
130};
131
junov@google.com53a55842011-06-08 22:55:10 +0000132void GrGpuGLShaders::abandonResources(){
133 INHERITED::abandonResources();
134 fProgramCache->abandon();
135}
136
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000137void GrGpuGLShaders::DeleteProgram(CachedData* programData) {
junov@google.comf93e7172011-03-31 21:26:24 +0000138 GR_GL(DeleteShader(programData->fVShaderID));
139 GR_GL(DeleteShader(programData->fFShaderID));
140 GR_GL(DeleteProgram(programData->fProgramID));
141 GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));)
142}
143
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000144////////////////////////////////////////////////////////////////////////////////
145
146namespace {
147 template <typename T>
148 T random_val(GrRandom* r, T count) {
149 return (T)(int)(r->nextF() * count);
150 }
151};
152
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000153void GrGpuGLShaders::ProgramUnitTest() {
154
155 static const int STAGE_OPTS[] = {
156 0,
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000157 StageDesc::kNoPerspective_OptFlagBit,
158 StageDesc::kIdentity_CoordMapping
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000159 };
160 GrGLProgram program;
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000161 ProgramDesc& pdesc = program.fProgramDesc;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000162
163 static const int NUM_TESTS = 512;
164
165 // GrRandoms nextU() values have patterns in the low bits
166 // So using nextU() % array_count might never take some values.
167 GrRandom random;
168 for (int t = 0; t < NUM_TESTS; ++t) {
169
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000170#if 0
171 GrPrintf("\nTest Program %d\n-------------\n", t);
172 static const int stop = -1;
173 if (t == stop) {
174 int breakpointhere = 9;
175 }
176#endif
177
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000178 pdesc.fVertexLayout = 0;
179 pdesc.fEmitsPointSize = random.nextF() > .5f;
180 float colorType = random.nextF();
181 if (colorType < 1.f / 3.f) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000182 pdesc.fColorType = ProgramDesc::kAttribute_ColorType;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000183 } else if (colorType < 2.f / 3.f) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000184 pdesc.fColorType = ProgramDesc::kUniform_ColorType;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000185 } else {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000186 pdesc.fColorType = ProgramDesc::kNone_ColorType;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000187 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000188
189 int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt));
190 pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx;
191
192 idx = (int)(random.nextF() * (kNumStages+1));
193 pdesc.fFirstCoverageStage = idx;
194
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000195 pdesc.fEdgeAANumEdges = (random.nextF() * (getMaxEdges() + 1));
senorblanco@chromium.org129b8e32011-06-15 17:52:09 +0000196 pdesc.fEdgeAAConcave = random.nextF() > .5f;
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000197
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000198 if (fDualSourceBlendingSupport) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000199 pdesc.fDualSrcOutput =
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000200 (ProgramDesc::DualSrcOutput)
201 (int)(random.nextF() * ProgramDesc::kDualSrcOutputCnt);
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000202 } else {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000203 pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000204 }
205
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000206 for (int s = 0; s < kNumStages; ++s) {
207 // enable the stage?
208 if (random.nextF() > .5f) {
209 // use separate tex coords?
210 if (random.nextF() > .5f) {
211 int t = (int)(random.nextF() * kMaxTexCoords);
212 pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
213 } else {
214 pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
215 }
216 }
217 // use text-formatted verts?
218 if (random.nextF() > .5f) {
219 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
220 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000221 idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000222 StageDesc& stage = pdesc.fStages[s];
223 stage.fOptFlags = STAGE_OPTS[idx];
224 stage.fModulation = random_val(&random, StageDesc::kModulationCnt);
225 stage.fCoordMapping = random_val(&random, StageDesc::kCoordMappingCnt);
226 stage.fFetchMode = random_val(&random, StageDesc::kFetchModeCnt);
227 stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout));
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000228 }
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000229 CachedData cachedData;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000230 program.genProgram(&cachedData);
231 DeleteProgram(&cachedData);
232 bool again = false;
233 if (again) {
234 program.genProgram(&cachedData);
235 DeleteProgram(&cachedData);
236 }
237 }
238}
239
junov@google.comf93e7172011-03-31 21:26:24 +0000240GrGpuGLShaders::GrGpuGLShaders() {
241
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000242 resetContext();
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000243
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000244 f4X4DownsampleFilterSupport = true;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000245 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000246 fDualSourceBlendingSupport =
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000247 fGLVersion >= 3.3f ||
248 this->hasExtension("GL_ARB_blend_func_extended");
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000249 } else {
250 fDualSourceBlendingSupport = false;
251 }
junov@google.comf93e7172011-03-31 21:26:24 +0000252
253 fProgramData = NULL;
254 fProgramCache = new ProgramCache();
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000255
256#if 0
257 ProgramUnitTest();
258#endif
junov@google.comf93e7172011-03-31 21:26:24 +0000259}
260
261GrGpuGLShaders::~GrGpuGLShaders() {
262 delete fProgramCache;
263}
264
265const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
junov@google.comf93e7172011-03-31 21:26:24 +0000266 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000267
268 if (GrGLProgram::kSetAsAttribute ==
269 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
270 return fHWDrawState.fSamplerStates[stage].getMatrix();
271 } else {
272 return fProgramData->fTextureMatrices[stage];
273 }
junov@google.comf93e7172011-03-31 21:26:24 +0000274}
275
276void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000277 GrAssert(fProgramData);
bsalomon@google.com91961302011-05-09 18:39:58 +0000278 if (GrGLProgram::kSetAsAttribute ==
279 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
280 fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
281 } else {
282 fProgramData->fTextureMatrices[stage] = matrix;
283 }
junov@google.comf93e7172011-03-31 21:26:24 +0000284}
285
286void GrGpuGLShaders::resetContext() {
287 INHERITED::resetContext();
junov@google.comf93e7172011-03-31 21:26:24 +0000288
junov@google.comf93e7172011-03-31 21:26:24 +0000289 fHWGeometryState.fVertexLayout = 0;
290 fHWGeometryState.fVertexOffset = ~0;
bsalomon@google.com91961302011-05-09 18:39:58 +0000291 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000292 for (int t = 0; t < kMaxTexCoords; ++t) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000293 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000294 }
bsalomon@google.com91961302011-05-09 18:39:58 +0000295 GR_GL(EnableVertexAttribArray(GrGLProgram::PositionAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000296
297 fHWProgramID = 0;
298}
299
300void GrGpuGLShaders::flushViewMatrix() {
301 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.comcc4dac32011-05-10 13:52:42 +0000302 GrMatrix m;
303 m.setAll(
junov@google.comf93e7172011-03-31 21:26:24 +0000304 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
305 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
306 0, 0, GrMatrix::I()[8]);
307 m.setConcat(m, fCurrDrawState.fViewMatrix);
308
309 // ES doesn't allow you to pass true to the transpose param,
310 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000311 GrGLfloat mt[] = {
312 GrScalarToFloat(m[GrMatrix::kMScaleX]),
313 GrScalarToFloat(m[GrMatrix::kMSkewY]),
314 GrScalarToFloat(m[GrMatrix::kMPersp0]),
315 GrScalarToFloat(m[GrMatrix::kMSkewX]),
316 GrScalarToFloat(m[GrMatrix::kMScaleY]),
317 GrScalarToFloat(m[GrMatrix::kMPersp1]),
318 GrScalarToFloat(m[GrMatrix::kMTransX]),
319 GrScalarToFloat(m[GrMatrix::kMTransY]),
320 GrScalarToFloat(m[GrMatrix::kMPersp2])
junov@google.comf93e7172011-03-31 21:26:24 +0000321 };
bsalomon@google.com91961302011-05-09 18:39:58 +0000322
323 if (GrGLProgram::kSetAsAttribute ==
324 fProgramData->fUniLocations.fViewMatrixUni) {
325 int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
326 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
327 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
328 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
329 } else {
330 GrAssert(GrGLProgram::kUnusedUniform !=
331 fProgramData->fUniLocations.fViewMatrixUni);
332 GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
333 1, false, mt));
334 }
junov@google.comf93e7172011-03-31 21:26:24 +0000335}
336
junov@google.com6acc9b32011-05-16 18:32:07 +0000337void GrGpuGLShaders::flushTextureDomain(int s) {
338 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
339 if (GrGLProgram::kUnusedUniform != uni) {
twiz@google.com76b82742011-06-02 20:30:02 +0000340 const GrRect &texDom =
junov@google.com6acc9b32011-05-16 18:32:07 +0000341 fCurrDrawState.fSamplerStates[s].getTextureDomain();
342
twiz@google.com76b82742011-06-02 20:30:02 +0000343 if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
344 fProgramData->fTextureDomain[s] != texDom) {
junov@google.com6acc9b32011-05-16 18:32:07 +0000345
junov@google.com2f839402011-05-24 15:13:01 +0000346 fProgramData->fTextureDomain[s] = texDom;
junov@google.com6acc9b32011-05-16 18:32:07 +0000347
junov@google.com2f839402011-05-24 15:13:01 +0000348 float values[4] = {
twiz@google.com76b82742011-06-02 20:30:02 +0000349 GrScalarToFloat(texDom.left()),
350 GrScalarToFloat(texDom.top()),
351 GrScalarToFloat(texDom.right()),
352 GrScalarToFloat(texDom.bottom())
junov@google.com2f839402011-05-24 15:13:01 +0000353 };
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];
twiz@google.com76b82742011-06-02 20:30:02 +0000362 // The top and bottom were just flipped, so correct the ordering
363 // of elements so that values = (l, t, r, b).
364 SkTSwap(values[1], values[3]);
junov@google.com2f839402011-05-24 15:13:01 +0000365 }
366
367 values[0] *= SkScalarToFloat(texture->contentScaleX());
368 values[2] *= SkScalarToFloat(texture->contentScaleX());
369 values[1] *= SkScalarToFloat(texture->contentScaleY());
370 values[3] *= SkScalarToFloat(texture->contentScaleY());
371
372 GR_GL(Uniform4fv(uni, 1, values));
junov@google.com6acc9b32011-05-16 18:32:07 +0000373 }
junov@google.com6acc9b32011-05-16 18:32:07 +0000374 }
375}
376
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000377void GrGpuGLShaders::flushTextureMatrix(int s) {
junov@google.com6acc9b32011-05-16 18:32:07 +0000378 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000379 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
380 if (NULL != texture) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000381 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000382 (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
383 getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
junov@google.comf93e7172011-03-31 21:26:24 +0000384
bsalomon@google.com91961302011-05-09 18:39:58 +0000385 GrAssert(NULL != fCurrDrawState.fTextures[s]);
junov@google.comf93e7172011-03-31 21:26:24 +0000386
bsalomon@google.com91961302011-05-09 18:39:58 +0000387 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000388
bsalomon@google.com91961302011-05-09 18:39:58 +0000389 GrMatrix m = getSamplerMatrix(s);
390 GrSamplerState::SampleMode mode =
391 fCurrDrawState.fSamplerStates[s].getSampleMode();
392 AdjustTextureMatrix(texture, mode, &m);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000393
bsalomon@google.com91961302011-05-09 18:39:58 +0000394 // ES doesn't allow you to pass true to the transpose param,
395 // so do our own transpose
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000396 GrGLfloat mt[] = {
397 GrScalarToFloat(m[GrMatrix::kMScaleX]),
398 GrScalarToFloat(m[GrMatrix::kMSkewY]),
399 GrScalarToFloat(m[GrMatrix::kMPersp0]),
400 GrScalarToFloat(m[GrMatrix::kMSkewX]),
401 GrScalarToFloat(m[GrMatrix::kMScaleY]),
402 GrScalarToFloat(m[GrMatrix::kMPersp1]),
403 GrScalarToFloat(m[GrMatrix::kMTransX]),
404 GrScalarToFloat(m[GrMatrix::kMTransY]),
405 GrScalarToFloat(m[GrMatrix::kMPersp2])
bsalomon@google.com91961302011-05-09 18:39:58 +0000406 };
bsalomon@google.com27a4dc42011-05-16 13:14:03 +0000407
bsalomon@google.com91961302011-05-09 18:39:58 +0000408 if (GrGLProgram::kSetAsAttribute ==
409 fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
410 int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s);
411 GR_GL(VertexAttrib4fv(baseIdx + 0, mt+0));
412 GR_GL(VertexAttrib4fv(baseIdx + 1, mt+3));
413 GR_GL(VertexAttrib4fv(baseIdx + 2, mt+6));
414 } else {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000415 GR_GL(UniformMatrix3fv(uni, 1, false, mt));
bsalomon@google.com91961302011-05-09 18:39:58 +0000416 }
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000417 recordHWSamplerMatrix(s, getSamplerMatrix(s));
418 }
419 }
junov@google.comf93e7172011-03-31 21:26:24 +0000420}
421
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000422void GrGpuGLShaders::flushRadial2(int s) {
junov@google.comf93e7172011-03-31 21:26:24 +0000423
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000424 const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
425 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com91961302011-05-09 18:39:58 +0000426 if (GrGLProgram::kUnusedUniform != uni &&
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000427 (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
428 fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
429 fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
junov@google.comf93e7172011-03-31 21:26:24 +0000430
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000431 GrScalar centerX1 = sampler.getRadial2CenterX1();
432 GrScalar radius0 = sampler.getRadial2Radius0();
junov@google.comf93e7172011-03-31 21:26:24 +0000433
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000434 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
junov@google.comf93e7172011-03-31 21:26:24 +0000435
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000436 float values[6] = {
437 GrScalarToFloat(a),
438 1 / (2.f * values[0]),
439 GrScalarToFloat(centerX1),
440 GrScalarToFloat(radius0),
441 GrScalarToFloat(GrMul(radius0, radius0)),
442 sampler.isRadial2PosRoot() ? 1.f : -1.f
443 };
444 GR_GL(Uniform1fv(uni, 6, values));
445 fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
446 fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0();
447 fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
448 }
449}
450
451void GrGpuGLShaders::flushTexelSize(int s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000452 const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
bsalomon@google.com91961302011-05-09 18:39:58 +0000453 if (GrGLProgram::kUnusedUniform != uni) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000454 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
455 if (texture->allocWidth() != fProgramData->fTextureWidth[s] ||
456 texture->allocHeight() != fProgramData->fTextureWidth[s]) {
457
458 float texelSize[] = {1.f / texture->allocWidth(),
459 1.f / texture->allocHeight()};
460 GR_GL(Uniform2fv(uni, 1, texelSize));
461 }
462 }
junov@google.comf93e7172011-03-31 21:26:24 +0000463}
464
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000465void GrGpuGLShaders::flushEdgeAAData() {
466 const int& uni = fProgramData->fUniLocations.fEdgesUni;
467 if (GrGLProgram::kUnusedUniform != uni) {
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000468 int count = fCurrDrawState.fEdgeAANumEdges;
469 Edge edges[kMaxEdges];
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000470 // Flip the edges in Y
471 float height = fCurrDrawState.fRenderTarget->height();
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000472 for (int i = 0; i < count; ++i) {
473 edges[i] = fCurrDrawState.fEdgeAAEdges[i];
474 float b = edges[i].fY;
475 edges[i].fY = -b;
476 edges[i].fZ += b * height;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000477 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000478 GR_GL(Uniform3fv(uni, count, &edges[0].fX));
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000479 }
480}
481
Scroggo01b87ec2011-05-11 18:05:38 +0000482static const float ONE_OVER_255 = 1.f / 255.f;
483
484#define GR_COLOR_TO_VEC4(color) {\
485 GrColorUnpackR(color) * ONE_OVER_255,\
486 GrColorUnpackG(color) * ONE_OVER_255,\
487 GrColorUnpackB(color) * ONE_OVER_255,\
488 GrColorUnpackA(color) * ONE_OVER_255 \
489}
490
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000491void GrGpuGLShaders::flushColor() {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000492 const ProgramDesc& desc = fCurrentProgram.getDesc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000493 if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000494 // color will be specified per-vertex as an attribute
495 // invalidate the const vertex attrib color
496 fHWDrawState.fColor = GrColor_ILLEGAL;
497 } else {
498 switch (desc.fColorType) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000499 case ProgramDesc::kAttribute_ColorType:
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000500 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
501 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000502 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000503 GR_GL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000504 fHWDrawState.fColor = fCurrDrawState.fColor;
505 }
506 break;
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000507 case ProgramDesc::kUniform_ColorType:
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000508 if (fProgramData->fColor != fCurrDrawState.fColor) {
509 // OpenGL ES only supports the float varities of glVertexAttrib
Scroggo01b87ec2011-05-11 18:05:38 +0000510 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColor);
bsalomon@google.com91961302011-05-09 18:39:58 +0000511 GrAssert(GrGLProgram::kUnusedUniform !=
512 fProgramData->fUniLocations.fColorUni);
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000513 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
514 fProgramData->fColor = fCurrDrawState.fColor;
515 }
516 break;
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000517 case ProgramDesc::kNone_ColorType:
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000518 GrAssert(0xffffffff == fCurrDrawState.fColor);
519 break;
520 default:
521 GrCrash("Unknown color type.");
522 }
523 }
Scroggo97c88c22011-05-11 14:05:25 +0000524 if (fProgramData->fUniLocations.fColorFilterUni
525 != GrGLProgram::kUnusedUniform
526 && fProgramData->fColorFilterColor
527 != fCurrDrawState.fColorFilterColor) {
Scroggo01b87ec2011-05-11 18:05:38 +0000528 float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
Scroggo97c88c22011-05-11 14:05:25 +0000529 GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
530 fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
531 }
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000532}
533
534
junov@google.comf93e7172011-03-31 21:26:24 +0000535bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
536 if (!flushGLStateCommon(type)) {
537 return false;
538 }
539
540 if (fDirtyFlags.fRenderTargetChanged) {
541 // our coords are in pixel space and the GL matrices map to NDC
542 // so if the viewport changed, our matrix is now wrong.
junov@google.comf93e7172011-03-31 21:26:24 +0000543 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
junov@google.comf93e7172011-03-31 21:26:24 +0000544 // we assume all shader matrices may be wrong after viewport changes
545 fProgramCache->invalidateViewMatrices();
junov@google.comf93e7172011-03-31 21:26:24 +0000546 }
547
junov@google.comf93e7172011-03-31 21:26:24 +0000548 buildProgram(type);
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000549 fProgramData = fProgramCache->getProgramData(fCurrentProgram);
bsalomon@google.com91961302011-05-09 18:39:58 +0000550 if (NULL == fProgramData) {
551 GrAssert(!"Failed to create program!");
552 return false;
553 }
junov@google.comf93e7172011-03-31 21:26:24 +0000554
555 if (fHWProgramID != fProgramData->fProgramID) {
556 GR_GL(UseProgram(fProgramData->fProgramID));
557 fHWProgramID = fProgramData->fProgramID;
558 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000559 GrBlendCoeff srcCoeff = fCurrDrawState.fSrcBlend;
560 GrBlendCoeff dstCoeff = fCurrDrawState.fDstBlend;
561
562 fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
563 this->flushBlend(type, srcCoeff, dstCoeff);
junov@google.comf93e7172011-03-31 21:26:24 +0000564
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000565 this->flushColor();
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000566
bsalomon@google.com91961302011-05-09 18:39:58 +0000567 GrMatrix* currViewMatrix;
568 if (GrGLProgram::kSetAsAttribute ==
569 fProgramData->fUniLocations.fViewMatrixUni) {
570 currViewMatrix = &fHWDrawState.fViewMatrix;
571 } else {
572 currViewMatrix = &fProgramData->fViewMatrix;
573 }
junov@google.comf93e7172011-03-31 21:26:24 +0000574
bsalomon@google.com91961302011-05-09 18:39:58 +0000575 if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
junov@google.comf93e7172011-03-31 21:26:24 +0000576 flushViewMatrix();
bsalomon@google.com91961302011-05-09 18:39:58 +0000577 *currViewMatrix = fCurrDrawState.fViewMatrix;
junov@google.comf93e7172011-03-31 21:26:24 +0000578 }
579
580 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000581 this->flushTextureMatrix(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000582
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000583 this->flushRadial2(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000584
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000585 this->flushTexelSize(s);
junov@google.com6acc9b32011-05-16 18:32:07 +0000586
587 this->flushTextureDomain(s);
junov@google.comf93e7172011-03-31 21:26:24 +0000588 }
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000589 this->flushEdgeAAData();
junov@google.comf93e7172011-03-31 21:26:24 +0000590 resetDirtyFlags();
591 return true;
592}
593
594void GrGpuGLShaders::postDraw() {
junov@google.comf93e7172011-03-31 21:26:24 +0000595}
596
597void GrGpuGLShaders::setupGeometry(int* startVertex,
598 int* startIndex,
599 int vertexCount,
600 int indexCount) {
601
602 int newColorOffset;
603 int newTexCoordOffsets[kMaxTexCoords];
604
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000605 GrGLsizei newStride = VertexSizeAndOffsetsByIdx(
606 this->getGeomSrc().fVertexLayout,
607 newTexCoordOffsets,
608 &newColorOffset);
junov@google.comf93e7172011-03-31 21:26:24 +0000609 int oldColorOffset;
610 int oldTexCoordOffsets[kMaxTexCoords];
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000611 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(
612 fHWGeometryState.fVertexLayout,
613 oldTexCoordOffsets,
614 &oldColorOffset);
junov@google.comf93e7172011-03-31 21:26:24 +0000615 bool indexed = NULL != startIndex;
616
617 int extraVertexOffset;
618 int extraIndexOffset;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000619 this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
junov@google.comf93e7172011-03-31 21:26:24 +0000620
621 GrGLenum scalarType;
622 bool texCoordNorm;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000623 if (this->getGeomSrc().fVertexLayout & kTextFormat_VertexLayoutBit) {
junov@google.comf93e7172011-03-31 21:26:24 +0000624 scalarType = GrGLTextType;
625 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
626 } else {
627 scalarType = GrGLType;
628 texCoordNorm = false;
629 }
630
631 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
632 *startVertex = 0;
633 if (indexed) {
634 *startIndex += extraIndexOffset;
635 }
636
637 // all the Pointers must be set if any of these are true
638 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
639 vertexOffset != fHWGeometryState.fVertexOffset ||
640 newStride != oldStride;
641
642 // position and tex coord offsets change if above conditions are true
643 // or the type/normalization changed based on text vs nontext type coords.
644 bool posAndTexChange = allOffsetsChange ||
645 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
646 (kTextFormat_VertexLayoutBit &
647 (fHWGeometryState.fVertexLayout ^
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000648 this->getGeomSrc().fVertexLayout)));
junov@google.comf93e7172011-03-31 21:26:24 +0000649
650 if (posAndTexChange) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000651 int idx = GrGLProgram::PositionAttributeIdx();
652 GR_GL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
653 (GrGLvoid*)vertexOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000654 fHWGeometryState.fVertexOffset = vertexOffset;
655 }
656
657 for (int t = 0; t < kMaxTexCoords; ++t) {
658 if (newTexCoordOffsets[t] > 0) {
659 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
bsalomon@google.com91961302011-05-09 18:39:58 +0000660 int idx = GrGLProgram::TexCoordAttributeIdx(t);
junov@google.comf93e7172011-03-31 21:26:24 +0000661 if (oldTexCoordOffsets[t] <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000662 GR_GL(EnableVertexAttribArray(idx));
663 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
664 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000665 } else if (posAndTexChange ||
666 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000667 GR_GL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
668 newStride, texCoordOffset));
junov@google.comf93e7172011-03-31 21:26:24 +0000669 }
670 } else if (oldTexCoordOffsets[t] > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000671 GR_GL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
junov@google.comf93e7172011-03-31 21:26:24 +0000672 }
673 }
674
675 if (newColorOffset > 0) {
676 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
bsalomon@google.com91961302011-05-09 18:39:58 +0000677 int idx = GrGLProgram::ColorAttributeIdx();
junov@google.comf93e7172011-03-31 21:26:24 +0000678 if (oldColorOffset <= 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000679 GR_GL(EnableVertexAttribArray(idx));
680 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000681 true, newStride, colorOffset));
682 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000683 GR_GL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
junov@google.comf93e7172011-03-31 21:26:24 +0000684 true, newStride, colorOffset));
685 }
686 } else if (oldColorOffset > 0) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000687 GR_GL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
junov@google.comf93e7172011-03-31 21:26:24 +0000688 }
689
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000690 fHWGeometryState.fVertexLayout = this->getGeomSrc().fVertexLayout;
junov@google.comf93e7172011-03-31 21:26:24 +0000691 fHWGeometryState.fArrayPtrsDirty = false;
692}
693
694void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000695 ProgramDesc& desc = fCurrentProgram.fProgramDesc;
junov@google.comf93e7172011-03-31 21:26:24 +0000696
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000697 // Must initialize all fields or cache will have false negatives!
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000698 desc.fVertexLayout = this->getGeomSrc().fVertexLayout;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000699
700 desc.fEmitsPointSize = kPoints_PrimitiveType == type;
701
702 bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
703 // fColorType records how colors are specified for the program. Strip
704 // the bit from the layout to avoid false negatives when searching for an
705 // existing program in the cache.
706 desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
707
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000708 desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode;
709
junov@google.comf93e7172011-03-31 21:26:24 +0000710#if GR_AGGRESSIVE_SHADER_OPTS
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000711 if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000712 desc.fColorType = ProgramDesc::kNone_ColorType;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000713 } else
junov@google.comf93e7172011-03-31 21:26:24 +0000714#endif
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000715#if GR_GL_NO_CONSTANT_ATTRIBUTES
716 if (!requiresAttributeColors) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000717 desc.fColorType = ProgramDesc::kUniform_ColorType;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000718 } else
719#endif
720 {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000721 if (requiresAttributeColors) {} // suppress unused var warning
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000722 desc.fColorType = ProgramDesc::kAttribute_ColorType;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000723 }
junov@google.comf93e7172011-03-31 21:26:24 +0000724
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000725 desc.fEdgeAANumEdges = fCurrDrawState.fEdgeAANumEdges;
senorblanco@chromium.org129b8e32011-06-15 17:52:09 +0000726 desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 && SkToBool(fCurrDrawState.fFlagBits & kEdgeAAConcave_StateBit);
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000727
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000728 int lastEnabledStage = -1;
729
junov@google.comf93e7172011-03-31 21:26:24 +0000730 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000731 StageDesc& stage = desc.fStages[s];
junov@google.comf93e7172011-03-31 21:26:24 +0000732
tomhudson@google.com0d831722011-06-02 15:37:14 +0000733 stage.fOptFlags = 0;
734 stage.setEnabled(this->isStageEnabled(s));
junov@google.comf93e7172011-03-31 21:26:24 +0000735
tomhudson@google.com0d831722011-06-02 15:37:14 +0000736 if (stage.isEnabled()) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000737 lastEnabledStage = s;
junov@google.comf93e7172011-03-31 21:26:24 +0000738 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
739 GrAssert(NULL != texture);
740 // we matrix to invert when orientation is TopDown, so make sure
741 // we aren't in that case before flagging as identity.
742 if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000743 stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
junov@google.comf93e7172011-03-31 21:26:24 +0000744 } else if (!getSamplerMatrix(s).hasPerspective()) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000745 stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
junov@google.comf93e7172011-03-31 21:26:24 +0000746 }
747 switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000748 case GrSamplerState::kNormal_SampleMode:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000749 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000750 break;
751 case GrSamplerState::kRadial_SampleMode:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000752 stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000753 break;
754 case GrSamplerState::kRadial2_SampleMode:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000755 stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000756 break;
757 case GrSamplerState::kSweep_SampleMode:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000758 stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000759 break;
760 default:
761 GrCrash("Unexpected sample mode!");
762 break;
763 }
764
765 switch (fCurrDrawState.fSamplerStates[s].getFilter()) {
766 // these both can use a regular texture2D()
767 case GrSamplerState::kNearest_Filter:
768 case GrSamplerState::kBilinear_Filter:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000769 stage.fFetchMode = StageDesc::kSingle_FetchMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000770 break;
771 // performs 4 texture2D()s
772 case GrSamplerState::k4x4Downsample_Filter:
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000773 stage.fFetchMode = StageDesc::k2x2_FetchMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000774 break;
775 default:
776 GrCrash("Unexpected filter!");
777 break;
junov@google.comf93e7172011-03-31 21:26:24 +0000778 }
779
junov@google.com6acc9b32011-05-16 18:32:07 +0000780 if (fCurrDrawState.fSamplerStates[s].hasTextureDomain()) {
tomhudson@google.com0d831722011-06-02 15:37:14 +0000781 GrAssert(GrSamplerState::kClamp_WrapMode ==
782 fCurrDrawState.fSamplerStates[s].getWrapX() &&
junov@google.com6acc9b32011-05-16 18:32:07 +0000783 GrSamplerState::kClamp_WrapMode ==
784 fCurrDrawState.fSamplerStates[s].getWrapY());
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000785 stage.fOptFlags |= StageDesc::kCustomTextureDomain_OptFlagBit;
junov@google.com6acc9b32011-05-16 18:32:07 +0000786 }
787
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000788 if (GrPixelConfigIsAlphaOnly(texture->config())) {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000789 stage.fModulation = StageDesc::kAlpha_Modulation;
junov@google.comf93e7172011-03-31 21:26:24 +0000790 } else {
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000791 stage.fModulation = StageDesc::kColor_Modulation;
junov@google.comf93e7172011-03-31 21:26:24 +0000792 }
junov@google.comf93e7172011-03-31 21:26:24 +0000793 } else {
794 stage.fOptFlags = 0;
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000795 stage.fCoordMapping = (StageDesc::CoordMapping)0;
796 stage.fModulation = (StageDesc::Modulation)0;
junov@google.comf93e7172011-03-31 21:26:24 +0000797 }
798 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000799
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000800 desc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000801 // use canonical value when coverage/color distinction won't affect
802 // generated code to prevent duplicate programs.
803 desc.fFirstCoverageStage = kNumStages;
804 if (fCurrDrawState.fFirstCoverageStage <= lastEnabledStage) {
805 // color filter is applied between color/coverage computation
806 if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
807 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
808 }
809
810 // We could consider cases where the final color is solid (0xff alpha)
811 // and the dst coeff can correctly be set to a non-dualsrc gl value.
812 // (e.g. solid draw, and dst coeff is kZero. It's correct to make
813 // the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
814 // kOne).
815 if (fDualSourceBlendingSupport) {
816 if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
817 // write the coverage value to second color
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000818 desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000819 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
820 } else if (kSA_BlendCoeff == fCurrDrawState.fDstBlend) {
821 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
822 // cover
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000823 desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000824 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
825 } else if (kSC_BlendCoeff == fCurrDrawState.fDstBlend) {
826 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
827 // cover
bsalomon@google.com1e257a52011-07-06 19:52:16 +0000828 desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000829 desc.fFirstCoverageStage = fCurrDrawState.fFirstCoverageStage;
830 }
831 }
832 }
junov@google.comf93e7172011-03-31 21:26:24 +0000833}