| 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 |