GrGpuGL_program.cpp revision 2c84aa35988c661b3e5513c8ba9b3959832ff288
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 10a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com#include "GrEffect.h" 11d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com#include "GrGLEffect.h" 122db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#include "SkTSearch.h" 13f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 14dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle; 15dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comstatic const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; 16dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com 172db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comstruct GrGpuGL::ProgramCache::Entry { 182db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SK_DECLARE_INST_COUNT_ROOT(Entry); 192db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry() : fProgram(NULL), fLRUStamp(0) {} 202db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 212db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkAutoTUnref<GrGLProgram> fProgram; 222db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com unsigned int fLRUStamp; 232db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com}; 242db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 252db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comSK_DEFINE_INST_COUNT(GrGpuGL::ProgramCache::Entry); 262db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 272db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comstruct GrGpuGL::ProgramCache::ProgDescLess { 282db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { 292db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != entry->fProgram.get()); 302db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); 312db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 322db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 332db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { 342db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != entry->fProgram.get()); 352db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); 362db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 372db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com}; 38f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 396177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.comGrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl) 40c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com : fCount(0) 41c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com , fCurrLRUStamp(0) 4291274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com , fGL(gl) 43948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 44948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com , fTotalRequests(0) 45948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com , fCacheMisses(0) 462db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com , fHashMisses(0) 47948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 48948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com{ 492db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < 1 << kHashBits; ++i) { 502db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[i] = NULL; 512db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 52948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com} 53948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com 54948787737b77555318fa2433e7ff941516fe950ejvanverth@google.comGrGpuGL::ProgramCache::~ProgramCache() { 552db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < fCount; ++i){ 562db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkDELETE(fEntries[i]); 572db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 58948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com // dump stats 59948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 60948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com SkDebugf("--- Program Cache ---\n"); 61948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com SkDebugf("Total requests: %d\n", fTotalRequests); 62948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com SkDebugf("Cache misses: %d\n", fCacheMisses); 632db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 642db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 100.f * fCacheMisses / fTotalRequests : 652db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 0.f); 662db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int cacheHits = fTotalRequests - fCacheMisses; 672db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); 68948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com SkDebugf("---------------------\n"); 69948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 70c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 71f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 72ecb60aad5c6fe5b1dbcfc86ac00bfc9326103c8dbsalomon@google.comvoid GrGpuGL::ProgramCache::abandon() { 73c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 0; i < fCount; ++i) { 742db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != fEntries[i]->fProgram.get()); 752db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[i]->fProgram->abandon(); 762db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[i]->fProgram.reset(NULL); 77f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 78c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com fCount = 0; 79c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 80f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 812db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comint GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { 822db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com ProgDescLess less; 832db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); 842db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com} 852db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 8631ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.comGrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, 872c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com const GrEffectStage* colorStages[], 882c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com const GrEffectStage* coverageStages[]) { 89948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 90948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com ++fTotalRequests; 91948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 929ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com 932db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry* entry = NULL; 942db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 952db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com uint32_t hashIdx = desc.getChecksum(); 962db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx ^= hashIdx >> 16; 972db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (kHashBits <= 8) { 982db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx ^= hashIdx >> 8; 992db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1002db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com hashIdx &=((1 << kHashBits) - 1); 1012db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com Entry* hashedEntry = fHashTable[hashIdx]; 1022db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) { 1032db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != hashedEntry->fProgram); 1042db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = hashedEntry; 1052db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1062db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1072db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int entryIdx; 1082db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (NULL == entry) { 1092db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entryIdx = this->search(desc); 1102db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (entryIdx >= 0) { 1112db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = fEntries[entryIdx]; 1122db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#ifdef PROGRAM_CACHE_STATS 1132db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com ++fHashMisses; 1142db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 1152db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1162db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1172db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 118c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com if (NULL == entry) { 1192db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // We have a cache miss 120948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#ifdef PROGRAM_CACHE_STATS 121948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com ++fCacheMisses; 122948787737b77555318fa2433e7ff941516fe950ejvanverth@google.com#endif 1232c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com GrGLProgram* program = GrGLProgram::Create(fGL, desc, colorStages, coverageStages); 1242db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (NULL == program) { 125c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com return NULL; 126c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } 1272db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int purgeIdx = 0; 128c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com if (fCount < kMaxEntries) { 1292db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = SkNEW(Entry); 1302db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = fCount++; 1312db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[purgeIdx] = entry; 132c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } else { 1332db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(fCount == kMaxEntries); 1342db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = 0; 135c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 1; i < kMaxEntries; ++i) { 1362db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { 1372db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com purgeIdx = i; 138f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 139f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 1402db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry = fEntries[purgeIdx]; 1412db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1); 1422db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (fHashTable[purgedHashIdx] == entry) { 1432db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[purgedHashIdx] = NULL; 1442db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 145f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 1462db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(fEntries[purgeIdx] == entry); 1472db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entry->fProgram.reset(program); 1482d816ad36e806e5b1cf3c447e547829bbbe74fd1skia.committer@gmail.com // We need to shift fEntries around so that the entry currently at purgeIdx is placed 1492db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). 1502db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com entryIdx = ~entryIdx; 1512db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (entryIdx < purgeIdx) { 1522db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // Let E and P be the entries at index entryIdx and purgeIdx, respectively. 1532db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // If the entries array looks like this: 1542db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaEbbbbbPccccc 1552db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // we rearrange it to look like this: 1562db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaPEbbbbbccccc 1572db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); 1582db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); 1592db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[entryIdx] = entry; 1602db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else if (purgeIdx < entryIdx) { 1612db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // If the entries array looks like this: 1622db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaaPbbbbbEccccc 1632db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // we rearrange it to look like this: 1642db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // aaaabbbbbPEccccc 1652db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); 1662db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); 1672db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[entryIdx - 1] = entry; 1682db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1692db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#if GR_DEBUG 1702db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != fEntries[0]->fProgram.get()); 1712db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com for (int i = 0; i < fCount - 1; ++i) { 1722db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(NULL != fEntries[i + 1]->fProgram.get()); 1732db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); 1742db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); 1752db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(GrGLProgramDesc::Less(a, b)); 1762db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com GrAssert(!GrGLProgramDesc::Less(b, a)); 1772db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 1782db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 179c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com } 180f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 1812db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fHashTable[hashIdx] = entry; 182c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com entry->fLRUStamp = fCurrLRUStamp; 1832db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1842db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com if (SK_MaxU32 == fCurrLRUStamp) { 185c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com // wrap around! just trash our LRU, one time hit. 186c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com for (int i = 0; i < fCount; ++i) { 1872db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com fEntries[i]->fLRUStamp = 0; 188f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 189f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 190c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com ++fCurrLRUStamp; 1919ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com return entry->fProgram; 192c1d2a58ec8510b226e080f5415a05723a686aab3bsalomon@google.com} 193f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 1941e257a5db32e1c9e3b0dba80f43470816ef948afbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1951e257a5db32e1c9e3b0dba80f43470816ef948afbsalomon@google.com 1965739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.comvoid GrGpuGL::abandonResources(){ 1975739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com INHERITED::abandonResources(); 1985739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com fProgramCache->abandon(); 1995739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com fHWProgramID = 0; 2005739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com} 2015739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com 2025739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 2035739d2c168819394502e20cbe6071979b9c1038cbsalomon@google.com 2040b77d6892b067ad402c9678b0226bff70599fbe2bsalomon@google.com#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 2050b77d6892b067ad402c9678b0226bff70599fbe2bsalomon@google.com 2066a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.comvoid GrGpuGL::flushPathStencilMatrix() { 2076a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix(); 2086a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 2096a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com SkISize size; 2106a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com size.set(rt->width(), rt->height()); 211b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix& vm = this->getDrawState().getViewMatrix(); 2128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com 2136a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com if (fHWPathStencilMatrixState.fRenderTargetOrigin != rt->origin() || 2146a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWPathStencilMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) || 2156a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWPathStencilMatrixState.fRenderTargetSize!= size) { 2166a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // rescale the coords from skia's "device" coords to GL's normalized coords, 2176a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // and perform a y-flip if required. 218b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix m; 2193cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { 2206a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height()); 2216a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com m.postTranslate(-SK_Scalar1, SK_Scalar1); 2223cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org } else { 2236a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height()); 2246a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com m.postTranslate(-SK_Scalar1, -SK_Scalar1); 2253cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org } 2266a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com m.preConcat(vm); 2278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com 2286a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // GL wants a column-major 4x4. 2296a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GrGLfloat mv[] = { 2306a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // col 0 231b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMScaleX]), 232b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMSkewY]), 2336a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 0, 234b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMPersp0]), 2356a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 2366a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // col 1 237b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMSkewX]), 238b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMScaleY]), 2396a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 0, 240b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMPersp1]), 2416a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 2426a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // col 2 2436a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 0, 0, 0, 0, 2446a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 2456a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // col3 246b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMTransX]), 247b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMTransY]), 2486a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 0.0f, 249b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkScalarToFloat(m[SkMatrix::kMPersp2]) 2508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com }; 2516a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GL_CALL(MatrixMode(GR_GL_PROJECTION)); 2526a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GL_CALL(LoadMatrixf(mv)); 2536a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWPathStencilMatrixState.fViewMatrix = vm; 2546a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWPathStencilMatrixState.fRenderTargetSize = size; 2556a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWPathStencilMatrixState.fRenderTargetOrigin = rt->origin(); 2569196130af83782fcac4334117142475a837dd74dbsalomon@google.com } 257f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com} 258f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 25926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.combool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { 2608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com const GrDrawState& drawState = this->getDrawState(); 2618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com 2626a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. 263c96cb3a929f954cd2e7b6319efdfa6b758b20bd3bsalomon@google.com GrAssert(NULL != drawState.getRenderTarget()); 264c96cb3a929f954cd2e7b6319efdfa6b758b20bd3bsalomon@google.com 2656a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com if (kStencilPath_DrawType == type) { 2666a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com this->flushPathStencilMatrix(); 2676a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com } else { 268ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com this->flushMiscFixedFunctionState(); 2694be283f3a82895530d1b70372cd48ddb1c663fd8bsalomon@google.com 270ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com GrBlendCoeff srcCoeff; 271ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com GrBlendCoeff dstCoeff; 2722b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); 2732b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { 274ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com return false; 275ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 276f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 2772c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com SkSTArray<8, const GrEffectStage*, true> colorStages; 2782c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com SkSTArray<8, const GrEffectStage*, true> coverageStages; 27931ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLProgramDesc desc; 28031ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLProgramDesc::Build(this->getDrawState(), 28191207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com kDrawPoints_DrawType == type, 28291207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com blendOpts, 28391207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com srcCoeff, 28491207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com dstCoeff, 28591207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com this, 28626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com dstCopy, 2872c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com &colorStages, 2882c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com &coverageStages, 28991207482c9398944fc997aeb99ed5f8674be58cbbsalomon@google.com &desc); 2909ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com 2912c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com fCurrentProgram.reset(fProgramCache->getProgram(desc, 2922c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com colorStages.begin(), 2932c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com coverageStages.begin())); 2949ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com if (NULL == fCurrentProgram.get()) { 295ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com GrAssert(!"Failed to create program!"); 296ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com return false; 297ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 2989ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com fCurrentProgram.get()->ref(); 2994c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 3006a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GrGLuint programID = fCurrentProgram->programID(); 3016a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com if (fHWProgramID != programID) { 3026a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com GL_CALL(UseProgram(programID)); 3036a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com fHWProgramID = programID; 304ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 3056a51dcbf81cff6d92996ab3f4c7457478e441896bsalomon@google.com 3069ba4fa6f0fb8ef496d81ccac36e780aa806fea83bsalomon@google.com fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 307ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 308ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com 3092c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com fCurrentProgram->setData(this, 3102c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com blendOpts, 3112c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com colorStages.begin(), 3122c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com coverageStages.begin(), 3132c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com dstCopy, 3142c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com &fSharedGLProgramState); 315f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com } 316ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com this->flushStencil(type); 317a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com this->flushScissor(); 318ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com this->flushAAState(type); 3194c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 3207b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect* devRect = NULL; 3217b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect devClipBounds; 3223e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com if (drawState.isClipState()) { 32302ddc8b85ace91b15feb329a6a1d5d62b2b846c6bsalomon@google.com this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); 3247b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com devRect = &devClipBounds; 3254c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com } 3264c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com // This must come after textures are flushed because a texture may need 3274c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com // to be msaa-resolved (which will modify bound FBO state). 3287b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com this->flushRenderTarget(devRect); 3294c8837867add05f8d25520f92f6ec52305dda02ebsalomon@google.com 330f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com return true; 331f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com} 332f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 333880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.comvoid GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { 334f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 3359b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrGLsizei stride = this->getDrawState().getVertexSize(); 336880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.com 3376918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com size_t vertexOffsetInBytes = stride * info.startVertex(); 3386918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3396918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 3406918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3416918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLVertexBuffer* vbuf; 3426918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com switch (this->getGeomSrc().fVertexSrc) { 3436918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kBuffer_GeometrySrcType: 3446918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 3456918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3466918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kArray_GeometrySrcType: 3476918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kReserved_GeometrySrcType: 3486918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com this->finalizeReservedVertices(); 3496918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize; 3506918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 3516918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3526918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com default: 3536918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf = NULL; // suppress warning 3546918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrCrash("Unknown geometry src type!"); 3556918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3566918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3576918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrAssert(NULL != vbuf); 3586918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrAssert(!vbuf->isLocked()); 3596918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexOffsetInBytes += vbuf->baseOffset(); 3606918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3616918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLIndexBuffer* ibuf = NULL; 3626918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com if (info.isIndexed()) { 3636918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrAssert(NULL != indexOffsetInBytes); 3646918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3656918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com switch (this->getGeomSrc().fIndexSrc) { 3666918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kBuffer_GeometrySrcType: 3676918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes = 0; 3686918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 3696918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3706918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kArray_GeometrySrcType: 3716918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com case kReserved_GeometrySrcType: 3726918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com this->finalizeReservedIndices(); 3736918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); 3746918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 3756918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com break; 3766918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com default: 3776918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com ibuf = NULL; // suppress warning 3786918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrCrash("Unknown geometry src type!"); 3796918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3806918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 3816918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrAssert(NULL != ibuf); 3826918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrAssert(!ibuf->isLocked()); 3836918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *indexOffsetInBytes += ibuf->baseOffset(); 3846918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 3856918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com GrGLAttribArrayState* attribState = 3866918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); 387880b8fcf255e67a15687e8b7cc47397372db683cbsalomon@google.com 3889b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com uint32_t usedAttribArraysMask = 0; 3899b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); 3909b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com int vertexAttribCount = this->getDrawState().getVertexAttribCount(); 391f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; 3929b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com ++vertexAttribIndex, ++vertexAttrib) { 393f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com 3949b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com usedAttribArraysMask |= (1 << vertexAttribIndex); 3959b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrVertexAttribType attribType = vertexAttrib->fType; 3966918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com attribState->set(this, 3976918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexAttribIndex, 3986918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vbuf, 39931ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLAttribTypeToLayout(attribType).fCount, 40031ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLAttribTypeToLayout(attribType).fType, 40131ec7985f2b52a0cab4aa714a613b918cf663c08bsalomon@google.com GrGLAttribTypeToLayout(attribType).fNormalized, 4026918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com stride, 4036918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com reinterpret_cast<GrGLvoid*>( 4046918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com vertexOffsetInBytes + vertexAttrib->fOffset)); 4056918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com } 4066918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com 4076918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com attribState->disableUnusedAttribArrays(this, usedAttribArraysMask); 408f93e717c7f7ca679a80acbfda6a34013ae1e2b8djunov@google.com} 409