OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGpuGL.h" | 8 #include "GrGpuGL.h" |
9 | 9 |
10 #include "builders/GrGLProgramBuilder.h" | 10 #include "builders/GrGLProgramBuilder.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 struct GrGpuGL::ProgramCache::Entry { | 25 struct GrGpuGL::ProgramCache::Entry { |
26 SK_DECLARE_INST_COUNT_ROOT(Entry); | 26 SK_DECLARE_INST_COUNT_ROOT(Entry); |
27 Entry() : fProgram(NULL), fLRUStamp(0) {} | 27 Entry() : fProgram(NULL), fLRUStamp(0) {} |
28 | 28 |
29 SkAutoTUnref<GrGLProgram> fProgram; | 29 SkAutoTUnref<GrGLProgram> fProgram; |
30 unsigned int fLRUStamp; | 30 unsigned int fLRUStamp; |
31 }; | 31 }; |
32 | 32 |
33 struct GrGpuGL::ProgramCache::ProgDescLess { | 33 struct GrGpuGL::ProgramCache::ProgDescLess { |
34 bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { | 34 bool operator() (const GrProgramDesc& desc, const Entry* entry) { |
35 SkASSERT(entry->fProgram.get()); | 35 SkASSERT(entry->fProgram.get()); |
36 return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); | 36 return GrProgramDesc::Less(desc, entry->fProgram->getDesc()); |
37 } | 37 } |
38 | 38 |
39 bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { | 39 bool operator() (const Entry* entry, const GrProgramDesc& desc) { |
40 SkASSERT(entry->fProgram.get()); | 40 SkASSERT(entry->fProgram.get()); |
41 return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); | 41 return GrProgramDesc::Less(entry->fProgram->getDesc(), desc); |
42 } | 42 } |
43 }; | 43 }; |
44 | 44 |
45 GrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu) | 45 GrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu) |
46 : fCount(0) | 46 : fCount(0) |
47 , fCurrLRUStamp(0) | 47 , fCurrLRUStamp(0) |
48 , fGpu(gpu) | 48 , fGpu(gpu) |
49 #ifdef PROGRAM_CACHE_STATS | 49 #ifdef PROGRAM_CACHE_STATS |
50 , fTotalRequests(0) | 50 , fTotalRequests(0) |
51 , fCacheMisses(0) | 51 , fCacheMisses(0) |
(...skipping 27 matching lines...) Expand all Loading... |
79 | 79 |
80 void GrGpuGL::ProgramCache::abandon() { | 80 void GrGpuGL::ProgramCache::abandon() { |
81 for (int i = 0; i < fCount; ++i) { | 81 for (int i = 0; i < fCount; ++i) { |
82 SkASSERT(fEntries[i]->fProgram.get()); | 82 SkASSERT(fEntries[i]->fProgram.get()); |
83 fEntries[i]->fProgram->abandon(); | 83 fEntries[i]->fProgram->abandon(); |
84 SkDELETE(fEntries[i]); | 84 SkDELETE(fEntries[i]); |
85 } | 85 } |
86 fCount = 0; | 86 fCount = 0; |
87 } | 87 } |
88 | 88 |
89 int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { | 89 int GrGpuGL::ProgramCache::search(const GrProgramDesc& desc) const { |
90 ProgDescLess less; | 90 ProgDescLess less; |
91 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); | 91 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); |
92 } | 92 } |
93 | 93 |
94 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, | 94 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, D
rawType type) { |
95 const GrGLProgramDesc& desc, | |
96 DrawType type) { | |
97 #ifdef PROGRAM_CACHE_STATS | 95 #ifdef PROGRAM_CACHE_STATS |
98 ++fTotalRequests; | 96 ++fTotalRequests; |
99 #endif | 97 #endif |
100 | 98 |
101 Entry* entry = NULL; | 99 Entry* entry = NULL; |
102 | 100 |
103 uint32_t hashIdx = desc.getChecksum(); | 101 uint32_t hashIdx = optState.desc().getChecksum(); |
104 hashIdx ^= hashIdx >> 16; | 102 hashIdx ^= hashIdx >> 16; |
105 if (kHashBits <= 8) { | 103 if (kHashBits <= 8) { |
106 hashIdx ^= hashIdx >> 8; | 104 hashIdx ^= hashIdx >> 8; |
107 } | 105 } |
108 hashIdx &=((1 << kHashBits) - 1); | 106 hashIdx &=((1 << kHashBits) - 1); |
109 Entry* hashedEntry = fHashTable[hashIdx]; | 107 Entry* hashedEntry = fHashTable[hashIdx]; |
110 if (hashedEntry && hashedEntry->fProgram->getDesc() == desc) { | 108 if (hashedEntry && hashedEntry->fProgram->getDesc() == optState.desc()) { |
111 SkASSERT(hashedEntry->fProgram); | 109 SkASSERT(hashedEntry->fProgram); |
112 entry = hashedEntry; | 110 entry = hashedEntry; |
113 } | 111 } |
114 | 112 |
115 int entryIdx; | 113 int entryIdx; |
116 if (NULL == entry) { | 114 if (NULL == entry) { |
117 entryIdx = this->search(desc); | 115 entryIdx = this->search(optState.desc()); |
118 if (entryIdx >= 0) { | 116 if (entryIdx >= 0) { |
119 entry = fEntries[entryIdx]; | 117 entry = fEntries[entryIdx]; |
120 #ifdef PROGRAM_CACHE_STATS | 118 #ifdef PROGRAM_CACHE_STATS |
121 ++fHashMisses; | 119 ++fHashMisses; |
122 #endif | 120 #endif |
123 } | 121 } |
124 } | 122 } |
125 | 123 |
126 if (NULL == entry) { | 124 if (NULL == entry) { |
127 // We have a cache miss | 125 // We have a cache miss |
128 #ifdef PROGRAM_CACHE_STATS | 126 #ifdef PROGRAM_CACHE_STATS |
129 ++fCacheMisses; | 127 ++fCacheMisses; |
130 #endif | 128 #endif |
131 GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc,
type, fGpu); | 129 GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, type,
fGpu); |
132 if (NULL == program) { | 130 if (NULL == program) { |
133 return NULL; | 131 return NULL; |
134 } | 132 } |
135 int purgeIdx = 0; | 133 int purgeIdx = 0; |
136 if (fCount < kMaxEntries) { | 134 if (fCount < kMaxEntries) { |
137 entry = SkNEW(Entry); | 135 entry = SkNEW(Entry); |
138 purgeIdx = fCount++; | 136 purgeIdx = fCount++; |
139 fEntries[purgeIdx] = entry; | 137 fEntries[purgeIdx] = entry; |
140 } else { | 138 } else { |
141 SkASSERT(fCount == kMaxEntries); | 139 SkASSERT(fCount == kMaxEntries); |
(...skipping 29 matching lines...) Expand all Loading... |
171 // we rearrange it to look like this: | 169 // we rearrange it to look like this: |
172 // aaaabbbbbPEccccc | 170 // aaaabbbbbPEccccc |
173 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); | 171 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); |
174 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); | 172 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); |
175 fEntries[entryIdx - 1] = entry; | 173 fEntries[entryIdx - 1] = entry; |
176 } | 174 } |
177 #ifdef SK_DEBUG | 175 #ifdef SK_DEBUG |
178 SkASSERT(fEntries[0]->fProgram.get()); | 176 SkASSERT(fEntries[0]->fProgram.get()); |
179 for (int i = 0; i < fCount - 1; ++i) { | 177 for (int i = 0; i < fCount - 1; ++i) { |
180 SkASSERT(fEntries[i + 1]->fProgram.get()); | 178 SkASSERT(fEntries[i + 1]->fProgram.get()); |
181 const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); | 179 const GrProgramDesc& a = fEntries[i]->fProgram->getDesc(); |
182 const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); | 180 const GrProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); |
183 SkASSERT(GrGLProgramDesc::Less(a, b)); | 181 SkASSERT(GrProgramDesc::Less(a, b)); |
184 SkASSERT(!GrGLProgramDesc::Less(b, a)); | 182 SkASSERT(!GrProgramDesc::Less(b, a)); |
185 } | 183 } |
186 #endif | 184 #endif |
187 } | 185 } |
188 | 186 |
189 fHashTable[hashIdx] = entry; | 187 fHashTable[hashIdx] = entry; |
190 entry->fLRUStamp = fCurrLRUStamp; | 188 entry->fLRUStamp = fCurrLRUStamp; |
191 | 189 |
192 if (SK_MaxU32 == fCurrLRUStamp) { | 190 if (SK_MaxU32 == fCurrLRUStamp) { |
193 // wrap around! just trash our LRU, one time hit. | 191 // wrap around! just trash our LRU, one time hit. |
194 for (int i = 0; i < fCount; ++i) { | 192 for (int i = 0; i < fCount; ++i) { |
195 fEntries[i]->fLRUStamp = 0; | 193 fEntries[i]->fLRUStamp = 0; |
196 } | 194 } |
197 } | 195 } |
198 ++fCurrLRUStamp; | 196 ++fCurrLRUStamp; |
199 return entry->fProgram; | 197 return entry->fProgram; |
200 } | 198 } |
201 | 199 |
202 //////////////////////////////////////////////////////////////////////////////// | 200 //////////////////////////////////////////////////////////////////////////////// |
203 | 201 |
204 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) | 202 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) |
205 | 203 |
206 bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
opy) { | 204 bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
opy) { |
207 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawSt
ate(), | 205 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawSt
ate(), |
208 *this->caps(), | 206 this, |
| 207 dstCopy, |
209 type)); | 208 type)); |
210 | 209 |
211 if (!optState) { | 210 if (!optState) { |
212 return false; | 211 return false; |
213 } | 212 } |
214 | 213 |
215 // GrGpu::setupClipAndFlushState should have already checked this and bailed
if not true. | 214 // GrGpu::setupClipAndFlushState should have already checked this and bailed
if not true. |
216 SkASSERT(optState->getRenderTarget()); | 215 SkASSERT(optState->getRenderTarget()); |
217 | 216 |
218 if (kStencilPath_DrawType == type) { | 217 if (kStencilPath_DrawType == type) { |
219 const GrRenderTarget* rt = optState->getRenderTarget(); | 218 const GrRenderTarget* rt = optState->getRenderTarget(); |
220 SkISize size; | 219 SkISize size; |
221 size.set(rt->width(), rt->height()); | 220 size.set(rt->width(), rt->height()); |
222 this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(),
size, rt->origin()); | 221 this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(),
size, rt->origin()); |
223 } else { | 222 } else { |
224 this->flushMiscFixedFunctionState(*optState.get()); | 223 this->flushMiscFixedFunctionState(*optState.get()); |
225 | 224 |
226 GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); | 225 GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); |
227 GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); | 226 GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); |
228 | 227 |
229 // In these blend coeff's we end up drawing nothing so we can skip draw
all together | 228 // In these blend coeff's we end up drawing nothing so we can skip draw
all together |
230 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && | 229 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && |
231 !optState->getStencil().doesWrite()) { | 230 !optState->getStencil().doesWrite()) { |
232 return false; | 231 return false; |
233 } | 232 } |
234 | 233 |
235 GrGLProgramDesc desc; | 234 fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), type)); |
236 if (!GrGLProgramDesc::Build(*optState.get(), type, this, dstCopy, &desc)
) { | |
237 SkDEBUGFAIL("Failed to generate GL program descriptor"); | |
238 return false; | |
239 } | |
240 | |
241 fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), desc, t
ype)); | |
242 if (NULL == fCurrentProgram.get()) { | 235 if (NULL == fCurrentProgram.get()) { |
243 SkDEBUGFAIL("Failed to create program!"); | 236 SkDEBUGFAIL("Failed to create program!"); |
244 return false; | 237 return false; |
245 } | 238 } |
246 | 239 |
247 fCurrentProgram.get()->ref(); | 240 fCurrentProgram.get()->ref(); |
248 | 241 |
249 GrGLuint programID = fCurrentProgram->programID(); | 242 GrGLuint programID = fCurrentProgram->programID(); |
250 if (fHWProgramID != programID) { | 243 if (fHWProgramID != programID) { |
251 GL_CALL(UseProgram(programID)); | 244 GL_CALL(UseProgram(programID)); |
(...skipping 18 matching lines...) Expand all Loading... |
270 } | 263 } |
271 // This must come after textures are flushed because a texture may need | 264 // This must come after textures are flushed because a texture may need |
272 // to be msaa-resolved (which will modify bound FBO state). | 265 // to be msaa-resolved (which will modify bound FBO state). |
273 this->flushRenderTarget(glRT, devRect); | 266 this->flushRenderTarget(glRT, devRect); |
274 | 267 |
275 return true; | 268 return true; |
276 } | 269 } |
277 | 270 |
278 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { | 271 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { |
279 SkAutoTUnref<GrOptDrawState> optState( | 272 SkAutoTUnref<GrOptDrawState> optState( |
280 GrOptDrawState::Create(this->getDrawState(), *this->caps(), | 273 GrOptDrawState::Create(this->getDrawState(), this, info.getDstCopy(), |
281 PrimTypeToDrawType(info.primitiveType()))); | 274 PrimTypeToDrawType(info.primitiveType()))); |
282 | 275 |
283 // If the optState would is NULL it should have been caught in flushGraphics
State before getting | 276 // If the optState would is NULL it should have been caught in flushGraphics
State before getting |
284 // here. | 277 // here. |
285 SkASSERT(optState); | 278 SkASSERT(optState); |
286 | 279 |
287 GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride()); | 280 GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride()); |
288 | 281 |
289 size_t vertexOffsetInBytes = stride * info.startVertex(); | 282 size_t vertexOffsetInBytes = stride * info.startVertex(); |
290 | 283 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 GrGLAttribTypeToLayout(attribType).fCount, | 345 GrGLAttribTypeToLayout(attribType).fCount, |
353 GrGLAttribTypeToLayout(attribType).fType, | 346 GrGLAttribTypeToLayout(attribType).fType, |
354 GrGLAttribTypeToLayout(attribType).fNormalized, | 347 GrGLAttribTypeToLayout(attribType).fNormalized, |
355 stride, | 348 stride, |
356 reinterpret_cast<GrGLvoid*>( | 349 reinterpret_cast<GrGLvoid*>( |
357 vertexOffsetInBytes + vertexAttrib->fOffset)); | 350 vertexOffsetInBytes + vertexAttrib->fOffset)); |
358 } | 351 } |
359 attribState->disableUnusedArrays(this, usedAttribArraysMask); | 352 attribState->disableUnusedArrays(this, usedAttribArraysMask); |
360 } | 353 } |
361 } | 354 } |
| 355 |
| 356 void GrGpuGL::buildKey(const GrOptDrawState* optState, |
| 357 GrGpu::DrawType drawType, |
| 358 const GrDeviceCoordTexture* dstCopy, |
| 359 GrProgramDesc* desc) { |
| 360 SkASSERT(optState); |
| 361 if (!GrGLProgramDesc::Build(*optState, drawType, this, dstCopy, desc)) { |
| 362 SkDEBUGFAIL("Failed to generate GL program descriptor"); |
| 363 } |
| 364 } |
OLD | NEW |