GrGpuGL_program.cpp revision 0a657bbc2c6fc9daf699942e023050536d5ec95f
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpuGL.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "GrEffect.h" 11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "GrGLEffect.h" 120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkRTConf.h" 13779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#include "SkTSearch.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef PROGRAM_CACHE_STATS 160a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerSK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, 170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger "Display program cache usage."); 180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#endif 190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef GrGLUniformManager::UniformHandle UniformHandle; 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenbergerstruct GrGpuGL::ProgramCache::Entry { 23779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger SK_DECLARE_INST_COUNT_ROOT(Entry); 24779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger Entry() : fProgram(NULL), fLRUStamp(0) {} 25779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 26779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger SkAutoTUnref<GrGLProgram> fProgram; 27779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger unsigned int fLRUStamp; 28779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger}; 29779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 30779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek SollenbergerSK_DEFINE_INST_COUNT(GrGpuGL::ProgramCache::Entry); 31779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 32779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenbergerstruct GrGpuGL::ProgramCache::ProgDescLess { 33779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { 340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != entry->fProgram.get()); 35779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); 36779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 37779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 38779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { 390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != entry->fProgram.get()); 40779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); 41779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 42779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger}; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 440a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerGrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu) 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : fCount(0) 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fCurrLRUStamp(0) 470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fGpu(gpu) 48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 49096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fTotalRequests(0) 50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fCacheMisses(0) 51779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger , fHashMisses(0) 52096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 53096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger{ 54779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < 1 << kHashBits; ++i) { 55779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[i] = NULL; 56779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 57096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 58096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 59096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerGrGpuGL::ProgramCache::~ProgramCache() { 60779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < fCount; ++i){ 61779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger SkDELETE(fEntries[i]); 62779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 63096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // dump stats 64096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (c_DisplayCache) { 660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("--- Program Cache ---\n"); 670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Total requests: %d\n", fTotalRequests); 680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Cache misses: %d\n", fCacheMisses); 690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 100.f * fCacheMisses / fTotalRequests : 710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 0.f); 720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int cacheHits = fTotalRequests - fCacheMisses; 730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); 740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("---------------------\n"); 750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 76096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGpuGL::ProgramCache::abandon() { 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < fCount; ++i) { 810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[i]->fProgram.get()); 82779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fProgram->abandon(); 83779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fProgram.reset(NULL); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCount = 0; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenbergerint GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { 89779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger ProgDescLess less; 90779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); 91779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger} 92779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, 9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const GrEffectStage* colorStages[], 9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const GrEffectStage* coverageStages[]) { 96096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 97096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ++fTotalRequests; 98096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 100779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger Entry* entry = NULL; 101779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 102779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger uint32_t hashIdx = desc.getChecksum(); 103779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx ^= hashIdx >> 16; 104779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (kHashBits <= 8) { 105779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx ^= hashIdx >> 8; 106779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 107779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx &=((1 << kHashBits) - 1); 108779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger Entry* hashedEntry = fHashTable[hashIdx]; 109779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) { 1100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != hashedEntry->fProgram); 111779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = hashedEntry; 112779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 113779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 114779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int entryIdx; 115779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL == entry) { 116779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entryIdx = this->search(desc); 117779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (entryIdx >= 0) { 118779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = fEntries[entryIdx]; 119779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#ifdef PROGRAM_CACHE_STATS 120779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger ++fHashMisses; 121779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif 122779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 123779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 124779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == entry) { 126779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // We have a cache miss 127096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 128096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ++fCacheMisses; 129096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 1300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLProgram* program = GrGLProgram::Create(fGpu, desc, colorStages, coverageStages); 131779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL == program) { 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 134779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int purgeIdx = 0; 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fCount < kMaxEntries) { 136779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = SkNEW(Entry); 137779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = fCount++; 138779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[purgeIdx] = entry; 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 1400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fCount == kMaxEntries); 141779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = 0; 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 1; i < kMaxEntries; ++i) { 143779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { 144779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = i; 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 147779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = fEntries[purgeIdx]; 148779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1); 149779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (fHashTable[purgedHashIdx] == entry) { 150779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[purgedHashIdx] = NULL; 151779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 1530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fEntries[purgeIdx] == entry); 154779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry->fProgram.reset(program); 155779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // We need to shift fEntries around so that the entry currently at purgeIdx is placed 156779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). 157779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entryIdx = ~entryIdx; 158779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (entryIdx < purgeIdx) { 159779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // Let E and P be the entries at index entryIdx and purgeIdx, respectively. 160779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // If the entries array looks like this: 161779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaEbbbbbPccccc 162779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // we rearrange it to look like this: 163779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaPEbbbbbccccc 164779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); 165779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); 166779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[entryIdx] = entry; 167779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } else if (purgeIdx < entryIdx) { 168779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // If the entries array looks like this: 169779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaPbbbbbEccccc 170779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // we rearrange it to look like this: 171779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaabbbbbPEccccc 172779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); 173779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); 174779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[entryIdx - 1] = entry; 175779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 1760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef SK_DEBUG 1770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[0]->fProgram.get()); 178779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < fCount - 1; ++i) { 1790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[i + 1]->fProgram.get()); 180779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); 181779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); 1820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(GrGLProgramDesc::Less(a, b)); 1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!GrGLProgramDesc::Less(b, a)); 184779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 185779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 188779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[hashIdx] = entry; 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fLRUStamp = fCurrLRUStamp; 190779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 191779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (SK_MaxU32 == fCurrLRUStamp) { 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // wrap around! just trash our LRU, one time hit. 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < fCount; ++i) { 194779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fLRUStamp = 0; 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ++fCurrLRUStamp; 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return entry->fProgram; 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////// 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGpuGL::abandonResources(){ 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::abandonResources(); 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fProgramCache->abandon(); 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHWProgramID = 0; 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////// 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrDrawState& drawState = this->getDrawState(); 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 216096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. 2170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != drawState.getRenderTarget()); 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 219096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (kStencilPath_DrawType == type) { 2200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 2210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkISize size; 2220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger size.set(rt->width(), rt->height()); 2230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); 224096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushMiscFixedFunctionState(); 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrBlendCoeff srcCoeff; 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrBlendCoeff dstCoeff; 229096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); 230096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkSTArray<8, const GrEffectStage*, true> colorStages; 23558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkSTArray<8, const GrEffectStage*, true> coverageStages; 2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLProgramDesc desc; 2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLProgramDesc::Build(this->getDrawState(), 238096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger kDrawPoints_DrawType == type, 239096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger blendOpts, 240096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger srcCoeff, 241096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger dstCoeff, 242096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this, 2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger dstCopy, 24458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &colorStages, 24558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &coverageStages, 246096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger &desc); 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger fCurrentProgram.reset(fProgramCache->getProgram(desc, 24958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger colorStages.begin(), 25058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger coverageStages.begin())); 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == fCurrentProgram.get()) { 2520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDEBUGFAIL("Failed to create program!"); 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 2560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(kDrawPath_DrawType != type || !fCurrentProgram->hasVertexShader()); 2570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCurrentProgram.get()->ref(); 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 260096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLuint programID = fCurrentProgram->programID(); 261096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fHWProgramID != programID) { 262096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GL_CALL(UseProgram(programID)); 263096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fHWProgramID = programID; 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 265096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fCurrentProgram->setData(blendOpts, 27058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger colorStages.begin(), 27158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger coverageStages.begin(), 27258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger dstCopy, 27358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &fSharedGLProgramState); 27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushStencil(type); 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushScissor(); 27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushAAState(type); 27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkIRect* devRect = NULL; 28058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkIRect devClipBounds; 28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (drawState.isClipState()) { 282d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru devRect = &devClipBounds; 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // This must come after textures are flushed because a texture may need 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to be msaa-resolved (which will modify bound FBO state). 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushRenderTarget(devRect); 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 292096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergervoid GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLsizei stride = this->getDrawState().getVertexSize(); 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger size_t vertexOffsetInBytes = stride * info.startVertex(); 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 298096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 300096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLVertexBuffer* vbuf; 301096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger switch (this->getGeomSrc().fVertexSrc) { 302096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kBuffer_GeometrySrcType: 303096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 304096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 305096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kArray_GeometrySrcType: 306096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kReserved_GeometrySrcType: 307096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this->finalizeReservedVertices(); 308096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize; 309096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 310096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 311096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger default: 312096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = NULL; // suppress warning 313096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrCrash("Unknown geometry src type!"); 31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != vbuf); 3170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!vbuf->isLocked()); 318096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vertexOffsetInBytes += vbuf->baseOffset(); 319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 320096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLIndexBuffer* ibuf = NULL; 321096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (info.isIndexed()) { 3220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != indexOffsetInBytes); 323096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 324096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger switch (this->getGeomSrc().fIndexSrc) { 325096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kBuffer_GeometrySrcType: 326096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes = 0; 327096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 328096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 329096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kArray_GeometrySrcType: 330096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kReserved_GeometrySrcType: 331096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this->finalizeReservedIndices(); 332096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); 333096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 334096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 335096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger default: 336096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = NULL; // suppress warning 337096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrCrash("Unknown geometry src type!"); 33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != ibuf); 3410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!ibuf->isLocked()); 342096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes += ibuf->baseOffset(); 34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 344096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLAttribArrayState* attribState = 345096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); 346096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 3470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!fCurrentProgram->hasVertexShader()) { 3480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int posIdx = this->getDrawState().positionAttributeIndex(); 3490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrVertexAttrib* vertexArray = this->getDrawState().getVertexAttribs() + posIdx; 3500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrVertexAttribType vertexArrayType = vertexArray->fType; 3510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!GrGLAttribTypeToLayout(vertexArrayType).fNormalized); 3520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(GrGLAttribTypeToLayout(vertexArrayType).fCount == 2); 3530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->setFixedFunctionVertexArray(this, 3540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vbuf, 3550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 2, 3560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(vertexArrayType).fType, 3570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger stride, 3580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger reinterpret_cast<GrGLvoid*>( 3590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexOffsetInBytes + vertexArray->fOffset)); 3600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->disableUnusedArrays(this, 0, true); 3610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } else { 3620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger uint32_t usedAttribArraysMask = 0; 3630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); 3640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int vertexAttribCount = this->getDrawState().getVertexAttribCount(); 3650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; 3660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger ++vertexAttribIndex, ++vertexAttrib) { 3670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 3680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger usedAttribArraysMask |= (1 << vertexAttribIndex); 3690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrVertexAttribType attribType = vertexAttrib->fType; 3700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->set(this, 3710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexAttribIndex, 3720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vbuf, 3730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fCount, 3740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fType, 3750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fNormalized, 3760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger stride, 3770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger reinterpret_cast<GrGLvoid*>( 3780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexOffsetInBytes + vertexAttrib->fOffset)); 3790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->disableUnusedArrays(this, usedAttribArraysMask, false); 3820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 384