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.programDesc().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.programDesc(
)) { |
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.programDesc()); |
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, | 204 bool GrGpuGL::flushGraphicsState(DrawType type, |
207 const ScissorState& scissorState, | 205 const ScissorState& scissorState, |
208 const GrDeviceCoordTexture* dstCopy) { | 206 const GrDeviceCoordTexture* dstCopy) { |
209 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawSt
ate(), | 207 SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawSt
ate(), |
210 *this->caps(), | 208 this, |
| 209 dstCopy, |
211 type)); | 210 type)); |
212 | 211 |
213 if (!optState) { | 212 if (!optState) { |
214 return false; | 213 return false; |
215 } | 214 } |
216 | 215 |
217 // GrGpu::setupClipAndFlushState should have already checked this and bailed
if not true. | 216 // GrGpu::setupClipAndFlushState should have already checked this and bailed
if not true. |
218 SkASSERT(optState->getRenderTarget()); | 217 SkASSERT(optState->getRenderTarget()); |
219 | 218 |
220 if (kStencilPath_DrawType == type) { | 219 if (kStencilPath_DrawType == type) { |
221 const GrRenderTarget* rt = optState->getRenderTarget(); | 220 const GrRenderTarget* rt = optState->getRenderTarget(); |
222 SkISize size; | 221 SkISize size; |
223 size.set(rt->width(), rt->height()); | 222 size.set(rt->width(), rt->height()); |
224 this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(),
size, rt->origin()); | 223 this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(),
size, rt->origin()); |
225 } else { | 224 } else { |
226 this->flushMiscFixedFunctionState(*optState.get()); | 225 this->flushMiscFixedFunctionState(*optState.get()); |
227 | 226 |
228 GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); | 227 GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); |
229 GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); | 228 GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); |
230 | 229 |
231 // In these blend coeff's we end up drawing nothing so we can skip draw
all together | 230 // In these blend coeff's we end up drawing nothing so we can skip draw
all together |
232 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && | 231 if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && |
233 !optState->getStencil().doesWrite()) { | 232 !optState->getStencil().doesWrite()) { |
234 return false; | 233 return false; |
235 } | 234 } |
236 | 235 |
237 GrGLProgramDesc desc; | 236 fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), type)); |
238 if (!GrGLProgramDesc::Build(*optState.get(), type, this, dstCopy, &desc)
) { | |
239 SkDEBUGFAIL("Failed to generate GL program descriptor"); | |
240 return false; | |
241 } | |
242 | |
243 fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), desc, t
ype)); | |
244 if (NULL == fCurrentProgram.get()) { | 237 if (NULL == fCurrentProgram.get()) { |
245 SkDEBUGFAIL("Failed to create program!"); | 238 SkDEBUGFAIL("Failed to create program!"); |
246 return false; | 239 return false; |
247 } | 240 } |
248 | 241 |
249 fCurrentProgram.get()->ref(); | 242 fCurrentProgram.get()->ref(); |
250 | 243 |
251 GrGLuint programID = fCurrentProgram->programID(); | 244 GrGLuint programID = fCurrentProgram->programID(); |
252 if (fHWProgramID != programID) { | 245 if (fHWProgramID != programID) { |
253 GL_CALL(UseProgram(programID)); | 246 GL_CALL(UseProgram(programID)); |
(...skipping 18 matching lines...) Expand all Loading... |
272 } | 265 } |
273 // This must come after textures are flushed because a texture may need | 266 // This must come after textures are flushed because a texture may need |
274 // to be msaa-resolved (which will modify bound FBO state). | 267 // to be msaa-resolved (which will modify bound FBO state). |
275 this->flushRenderTarget(glRT, devRect); | 268 this->flushRenderTarget(glRT, devRect); |
276 | 269 |
277 return true; | 270 return true; |
278 } | 271 } |
279 | 272 |
280 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { | 273 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { |
281 SkAutoTUnref<GrOptDrawState> optState( | 274 SkAutoTUnref<GrOptDrawState> optState( |
282 GrOptDrawState::Create(this->getDrawState(), *this->caps(), | 275 GrOptDrawState::Create(this->getDrawState(), this, info.getDstCopy(), |
283 PrimTypeToDrawType(info.primitiveType()))); | 276 PrimTypeToDrawType(info.primitiveType()))); |
284 | 277 |
285 // If the optState would is NULL it should have been caught in flushGraphics
State before getting | 278 // If the optState would is NULL it should have been caught in flushGraphics
State before getting |
286 // here. | 279 // here. |
287 SkASSERT(optState); | 280 SkASSERT(optState); |
288 | 281 |
289 GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride()); | 282 GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride()); |
290 | 283 |
291 size_t vertexOffsetInBytes = stride * info.startVertex(); | 284 size_t vertexOffsetInBytes = stride * info.startVertex(); |
292 | 285 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 GrGLAttribTypeToLayout(attribType).fCount, | 347 GrGLAttribTypeToLayout(attribType).fCount, |
355 GrGLAttribTypeToLayout(attribType).fType, | 348 GrGLAttribTypeToLayout(attribType).fType, |
356 GrGLAttribTypeToLayout(attribType).fNormalized, | 349 GrGLAttribTypeToLayout(attribType).fNormalized, |
357 stride, | 350 stride, |
358 reinterpret_cast<GrGLvoid*>( | 351 reinterpret_cast<GrGLvoid*>( |
359 vertexOffsetInBytes + vertexAttrib->fOffset)); | 352 vertexOffsetInBytes + vertexAttrib->fOffset)); |
360 } | 353 } |
361 attribState->disableUnusedArrays(this, usedAttribArraysMask); | 354 attribState->disableUnusedArrays(this, usedAttribArraysMask); |
362 } | 355 } |
363 } | 356 } |
| 357 |
| 358 void GrGpuGL::buildProgramDesc(const GrOptDrawState& optState, |
| 359 const GrProgramDesc::DescInfo& descInfo, |
| 360 GrGpu::DrawType drawType, |
| 361 const GrDeviceCoordTexture* dstCopy, |
| 362 GrProgramDesc* desc) { |
| 363 if (!GrGLProgramDescBuilder::Build(optState, descInfo, drawType, this, dstCo
py, desc)) { |
| 364 SkDEBUGFAIL("Failed to generate GL program descriptor"); |
| 365 } |
| 366 } |
OLD | NEW |