GrGLGpuProgramCache.cpp revision 47bb38283072dc87dc93220cd2f370ca109972ff
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com */ 7f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 85739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com#include "GrGpuGL.h" 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 1047bb38283072dc87dc93220cd2f370ca109972ffjoshualitt#include "builders/GrGLProgramBuilder.h" 11b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h" 12b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrGLProcessor.h" 138a4c1030ff4b8336b5ac5b0712691e2f65383440egdaniel#include "GrGLPathRendering.h" 14170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel#include "GrOptDrawState.h" 15170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel#include "SkRTConf.h" 162db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#include "SkTSearch.h" 17f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 18a2f4b15d4e861b8b29e20ec37743fd3fd4b05b03jvanverth@google.com#ifdef PROGRAM_CACHE_STATS 195c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.comSK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, 205c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com "Display program cache usage."); 21a2f4b15d4e861b8b29e20ec37743fd3fd4b05b03jvanverth@google.com#endif 225c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com 237510b224e52b9518a8ddf7418db0e9c258f79539kkinnunentypedef GrGLProgramDataManager::UniformHandle UniformHandle; 24dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com 252db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comstruct GrGpuGL::ProgramCache::Entry { 262db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SK_DECLARE_INST_COUNT_ROOT(Entry); 272db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry() : fProgram(NULL), fLRUStamp(0) {} 282db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 292db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkAutoTUnref<GrGLProgram> fProgram; 302db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com unsigned int fLRUStamp; 312db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com}; 322db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 332db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comstruct GrGpuGL::ProgramCache::ProgDescLess { 342db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { 3549f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(entry->fProgram.get()); 362db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); 372db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 382db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 392db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { 4049f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(entry->fProgram.get()); 412db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); 422db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 432db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com}; 44f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 459188a15f846ae79892c332aed2a72ee38116bdc6commit-bot@chromium.orgGrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu) 46c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com : fCount(0) 47c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com , fCurrLRUStamp(0) 489188a15f846ae79892c332aed2a72ee38116bdc6commit-bot@chromium.org , fGpu(gpu) 49948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 50948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com , fTotalRequests(0) 51948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com , fCacheMisses(0) 522db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com , fHashMisses(0) 53948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 54948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com{ 552db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < 1 << kHashBits; ++i) { 562db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[i] = NULL; 572db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 58948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com} 59948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com 60948787737b77555318fa2433e7ff941516fe950ejvanverth@google.comGrGpuGL::ProgramCache::~ProgramCache() { 612db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < fCount; ++i){ 622db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkDELETE(fEntries[i]); 632db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 64948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com // dump stats 65948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 665c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com if (c_DisplayCache) { 675c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("--- Program Cache ---\n"); 685c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("Total requests: %d\n", fTotalRequests); 695c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("Cache misses: %d\n", fCacheMisses); 705c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 715c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com 100.f * fCacheMisses / fTotalRequests : 725c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com 0.f); 735c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com int cacheHits = fTotalRequests - fCacheMisses; 745c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); 755c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com SkDebugf("---------------------\n"); 765c9b6faefff735110a59932793e81cf5b9dec51djvanverth@google.com } 77948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 78c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 79f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 80ecb60aad5c6fe5b1dbcfc86ac00bfc9326103c8dbsalomon@google.comvoid GrGpuGL::ProgramCache::abandon() { 81c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 0; i < fCount; ++i) { 8249f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fEntries[i]->fProgram.get()); 832db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[i]->fProgram->abandon(); 84944bcf0acb78f8f9da01e991f1307629959e338absalomon SkDELETE(fEntries[i]); 85f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 86c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com fCount = 0; 87c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 88f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 892db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comint GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { 902db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com ProgDescLess less; 912db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); 922db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com} 932db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 94307796bc2e3731099d96773db7385fe70cb94f7degdanielGrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState, 95307796bc2e3731099d96773db7385fe70cb94f7degdaniel const GrGLProgramDesc& desc, 9647bb38283072dc87dc93220cd2f370ca109972ffjoshualitt DrawType type, 97b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGeometryStage* geometryProcessor, 98b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentStage* colorStages[], 99b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentStage* coverageStages[]) { 100948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 101948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com ++fTotalRequests; 102948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 1039ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com 1042db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry* entry = NULL; 1052db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1062db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com uint32_t hashIdx = desc.getChecksum(); 1072db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx ^= hashIdx >> 16; 1082db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (kHashBits <= 8) { 1092db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx ^= hashIdx >> 8; 1102db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1112db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx &=((1 << kHashBits) - 1); 1122db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry* hashedEntry = fHashTable[hashIdx]; 11349f085dddff10473b6ebf832a974288300224e60bsalomon if (hashedEntry && hashedEntry->fProgram->getDesc() == desc) { 11449f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(hashedEntry->fProgram); 1152db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = hashedEntry; 1162db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1172db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1182db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int entryIdx; 1192db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (NULL == entry) { 1202db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entryIdx = this->search(desc); 1212db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (entryIdx >= 0) { 1222db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = fEntries[entryIdx]; 1232db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#ifdef PROGRAM_CACHE_STATS 1242db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com ++fHashMisses; 1252db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 1262db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1272db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1282db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 129c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com if (NULL == entry) { 1302db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // We have a cache miss 131948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 132948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com ++fCacheMisses; 133948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 13447bb38283072dc87dc93220cd2f370ca109972ffjoshualitt GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type, 13547bb38283072dc87dc93220cd2f370ca109972ffjoshualitt geometryProcessor, colorStages, 13647bb38283072dc87dc93220cd2f370ca109972ffjoshualitt coverageStages, fGpu); 1372db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (NULL == program) { 138c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com return NULL; 139c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } 1402db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int purgeIdx = 0; 141c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com if (fCount < kMaxEntries) { 1422db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = SkNEW(Entry); 1432db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = fCount++; 1442db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[purgeIdx] = entry; 145c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } else { 146f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(fCount == kMaxEntries); 1472db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = 0; 148c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 1; i < kMaxEntries; ++i) { 1492db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { 1502db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = i; 151f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 152f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 1532db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = fEntries[purgeIdx]; 1542db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1); 1552db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (fHashTable[purgedHashIdx] == entry) { 1562db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[purgedHashIdx] = NULL; 1572db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 158f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 159f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(fEntries[purgeIdx] == entry); 1602db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry->fProgram.reset(program); 1612d816ad36e806e5b1cf3c447e547829bbbe74fd1skia.committer@gmail.com // We need to shift fEntries around so that the entry currently at purgeIdx is placed 1622db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). 1632db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entryIdx = ~entryIdx; 1642db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (entryIdx < purgeIdx) { 1652db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // Let E and P be the entries at index entryIdx and purgeIdx, respectively. 1662db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // If the entries array looks like this: 1672db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaEbbbbbPccccc 1682db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // we rearrange it to look like this: 1692db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaPEbbbbbccccc 1702db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); 1712db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); 1722db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[entryIdx] = entry; 1732db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else if (purgeIdx < entryIdx) { 1742db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // If the entries array looks like this: 1752db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaPbbbbbEccccc 1762db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // we rearrange it to look like this: 1772db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaabbbbbPEccccc 1782db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); 1792db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); 1802db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[entryIdx - 1] = entry; 1812db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 182515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG 18349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fEntries[0]->fProgram.get()); 1842db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < fCount - 1; ++i) { 18549f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(fEntries[i + 1]->fProgram.get()); 1862db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); 1872db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); 188f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(GrGLProgramDesc::Less(a, b)); 189f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!GrGLProgramDesc::Less(b, a)); 1902db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1912db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 192c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } 193f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 1942db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[hashIdx] = entry; 195c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com entry->fLRUStamp = fCurrLRUStamp; 1962db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1972db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (SK_MaxU32 == fCurrLRUStamp) { 198c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com // wrap around! just trash our LRU, one time hit. 199c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 0; i < fCount; ++i) { 2002db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[i]->fLRUStamp = 0; 201f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 202f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 203c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com ++fCurrLRUStamp; 2049ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com return entry->fProgram; 205c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 206f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 2071e257a5db32e1c9e3b0dba80f43470816ef948afbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 2081e257a5db32e1c9e3b0dba80f43470816ef948afbsalomon@google.com 2090b77d6892b067ad402c9678b0226bff70599fbe2bsalomon@google.com#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 2100b77d6892b067ad402c9678b0226bff70599fbe2bsalomon@google.com 21126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.combool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { 212b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(), 213b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel *this->caps(), 214b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel type)); 215b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel 216b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel if (!optState) { 217b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel return false; 218b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel } 2198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com 2206a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. 221170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel SkASSERT(optState->getRenderTarget()); 222c96cb3a929f954cd2e7b6319efdfa6b758b20bd3bsalomon@google.com 2236a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com if (kStencilPath_DrawType == type) { 224170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel const GrRenderTarget* rt = optState->getRenderTarget(); 2256b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org SkISize size; 2266b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org size.set(rt->width(), rt->height()); 227170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(), size, rt->origin()); 2286a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com } else { 229d632ea4b9eec5be3f83a9fa4982a30202e1239a7egdaniel this->flushMiscFixedFunctionState(*optState.get()); 2304be283f3a82895530d1b70372cd48ddb1c663fd8bsalomon@google.com 231170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff(); 232170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel GrBlendCoeff dstCoeff = optState->getDstBlendCoeff(); 233170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 234170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel // In these blend coeff's we end up drawing nothing so we can skip draw all together 235170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff && 236170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel !optState->getStencil().doesWrite()) { 237ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com return false; 238ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 239f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 240b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGeometryStage* geometryProcessor = NULL; 241b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkSTArray<8, const GrFragmentStage*, true> colorStages; 242b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkSTArray<8, const GrFragmentStage*, true> coverageStages; 24331ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLProgramDesc desc; 244170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (!GrGLProgramDesc::Build(*optState.get(), 245d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt type, 246d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt srcCoeff, 247d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt dstCoeff, 248d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt this, 249d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt dstCopy, 250d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt &geometryProcessor, 251d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt &colorStages, 252d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt &coverageStages, 253d909759832d5a6bb476597098e05bbe7ba0ccbd2joshualitt &desc)) { 254848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon SkDEBUGFAIL("Failed to generate GL program descriptor"); 255848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon return false; 256848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon } 2579ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com 258307796bc2e3731099d96773db7385fe70cb94f7degdaniel fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), 259307796bc2e3731099d96773db7385fe70cb94f7degdaniel desc, 26047bb38283072dc87dc93220cd2f370ca109972ffjoshualitt type, 261bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt geometryProcessor, 2622c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com colorStages.begin(), 2632c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com coverageStages.begin())); 2649ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com if (NULL == fCurrentProgram.get()) { 265330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com SkDEBUGFAIL("Failed to create program!"); 266ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com return false; 267ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 268c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org 2699ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com fCurrentProgram.get()->ref(); 2704c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 2716a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GrGLuint programID = fCurrentProgram->programID(); 2726a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com if (fHWProgramID != programID) { 2736a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GL_CALL(UseProgram(programID)); 2746a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWProgramID = programID; 275ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 2766a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 277d632ea4b9eec5be3f83a9fa4982a30202e1239a7egdaniel this->flushBlend(*optState.get(), kDrawLines_DrawType == type, srcCoeff, dstCoeff); 278ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com 279170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel fCurrentProgram->setData(*optState.get(), 280170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel type, 281bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt geometryProcessor, 2822c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com colorStages.begin(), 2832c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com coverageStages.begin(), 2842c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com dstCopy, 2852c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com &fSharedGLProgramState); 286f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 287b0bd4f64a6827dda6f4ec48e4746b0f0b72a975fbsalomon 288170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(optState->getRenderTarget()); 289ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com this->flushStencil(type); 290b0bd4f64a6827dda6f4ec48e4746b0f0b72a975fbsalomon this->flushScissor(glRT->getViewport(), glRT->origin()); 291d632ea4b9eec5be3f83a9fa4982a30202e1239a7egdaniel this->flushAAState(*optState.get(), type); 2924c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 293fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect* devRect = NULL; 294fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect devClipBounds; 295170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (optState->isClipState()) { 296170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel this->getClip()->getConservativeBounds(optState->getRenderTarget(), &devClipBounds); 2977b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com devRect = &devClipBounds; 2984c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com } 2994c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com // This must come after textures are flushed because a texture may need 3004c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com // to be msaa-resolved (which will modify bound FBO state). 301b0bd4f64a6827dda6f4ec48e4746b0f0b72a975fbsalomon this->flushRenderTarget(glRT, devRect); 3024c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 303f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com return true; 304f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com} 305f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 306880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.comvoid GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { 307b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel SkAutoTUnref<GrOptDrawState> optState( 308b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel GrOptDrawState::Create(this->getDrawState(), *this->caps(), 309b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel PrimTypeToDrawType(info.primitiveType()))); 310b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel 311b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel // If the optState would is NULL it should have been caught in flushGraphicsState before getting 312b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel // here. 313b109ac22b4ec3ab3478f5304c96564a0e9df6170egdaniel SkASSERT(optState); 314f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 315170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride()); 316880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.com 3176918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com size_t vertexOffsetInBytes = stride * info.startVertex(); 3186918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3196918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 3206918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3216918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLVertexBuffer* vbuf; 3226918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com switch (this->getGeomSrc().fVertexSrc) { 3236918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kBuffer_GeometrySrcType: 3246918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 3256918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3266918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kArray_GeometrySrcType: 3276918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kReserved_GeometrySrcType: 3286918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com this->finalizeReservedVertices(); 3296918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize; 3306918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 3316918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3326918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com default: 3336918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = NULL; // suppress warning 33488cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Unknown geometry src type!"); 3356918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3366918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 33749f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(vbuf); 3388341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org SkASSERT(!vbuf->isMapped()); 3396918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexOffsetInBytes += vbuf->baseOffset(); 3406918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3416918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLIndexBuffer* ibuf = NULL; 3426918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com if (info.isIndexed()) { 34349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(indexOffsetInBytes); 3446918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3456918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com switch (this->getGeomSrc().fIndexSrc) { 3466918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kBuffer_GeometrySrcType: 3476918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes = 0; 3486918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 3496918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3506918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kArray_GeometrySrcType: 3516918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kReserved_GeometrySrcType: 3526918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com this->finalizeReservedIndices(); 3536918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); 3546918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 3556918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3566918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com default: 3576918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = NULL; // suppress warning 35888cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Unknown geometry src type!"); 3596918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3606918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 36149f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(ibuf); 3628341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org SkASSERT(!ibuf->isMapped()); 3636918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes += ibuf->baseOffset(); 3646918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3656918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLAttribArrayState* attribState = 3666918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); 367880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.com 3680a6fe71f1bc0e601b41b7ae6d28b8c96a2c41116commit-bot@chromium.org if (fCurrentProgram->hasVertexShader()) { 369170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel int vertexAttribCount = optState->getVertexAttribCount(); 3706b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org uint32_t usedAttribArraysMask = 0; 371170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel const GrVertexAttrib* vertexAttrib = optState->getVertexAttribs(); 37202cafcc1bf6e2968c2efdf459871167970da150eegdaniel 3736b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; 3746b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org ++vertexAttribIndex, ++vertexAttrib) { 3756b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org usedAttribArraysMask |= (1 << vertexAttribIndex); 3766b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org GrVertexAttribType attribType = vertexAttrib->fType; 3776b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org attribState->set(this, 3786b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org vertexAttribIndex, 3796b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org vbuf, 3806b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org GrGLAttribTypeToLayout(attribType).fCount, 3816b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org GrGLAttribTypeToLayout(attribType).fType, 3826b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org GrGLAttribTypeToLayout(attribType).fNormalized, 3836b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org stride, 3846b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org reinterpret_cast<GrGLvoid*>( 3856ebfbf9968c76b0238f1b48296ff1b507e110ba1commit-bot@chromium.org vertexOffsetInBytes + vertexAttrib->fOffset)); 3866b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org } 3876ebfbf9968c76b0238f1b48296ff1b507e110ba1commit-bot@chromium.org attribState->disableUnusedArrays(this, usedAttribArraysMask); 3886b30e457409f37c91c301cd82040e733e2930286commit-bot@chromium.org } 389f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com} 390