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 Sollenbergerstruct GrGpuGL::ProgramCache::ProgDescLess { 31779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger bool operator() (const GrGLProgramDesc& desc, const Entry* entry) { 320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != entry->fProgram.get()); 33779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc()); 34779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 35779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 36779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger bool operator() (const Entry* entry, const GrGLProgramDesc& desc) { 370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != entry->fProgram.get()); 38779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc); 39779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 40779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger}; 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 420a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerGrGpuGL::ProgramCache::ProgramCache(GrGpuGL* gpu) 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : fCount(0) 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fCurrLRUStamp(0) 450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fGpu(gpu) 46096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 47096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fTotalRequests(0) 48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fCacheMisses(0) 49779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger , fHashMisses(0) 50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 51096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger{ 52779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < 1 << kHashBits; ++i) { 53779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[i] = NULL; 54779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 55096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 56096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 57096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerGrGpuGL::ProgramCache::~ProgramCache() { 58779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < fCount; ++i){ 59779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger SkDELETE(fEntries[i]); 60779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 61096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // dump stats 62096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (c_DisplayCache) { 640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("--- Program Cache ---\n"); 650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Total requests: %d\n", fTotalRequests); 660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Cache misses: %d\n", fCacheMisses); 670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? 680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 100.f * fCacheMisses / fTotalRequests : 690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 0.f); 700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int cacheHits = fTotalRequests - fCacheMisses; 710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); 720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("---------------------\n"); 730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 74096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGpuGL::ProgramCache::abandon() { 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < fCount; ++i) { 790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[i]->fProgram.get()); 80779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fProgram->abandon(); 81779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fProgram.reset(NULL); 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCount = 0; 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 86779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenbergerint GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const { 87779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger ProgDescLess less; 88779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); 89779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger} 90779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, 9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const GrEffectStage* colorStages[], 9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const GrEffectStage* coverageStages[]) { 94096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 95096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ++fTotalRequests; 96096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 98779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger Entry* entry = NULL; 99779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 100779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger uint32_t hashIdx = desc.getChecksum(); 101779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx ^= hashIdx >> 16; 102779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (kHashBits <= 8) { 103779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx ^= hashIdx >> 8; 104779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 105779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger hashIdx &=((1 << kHashBits) - 1); 106779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger Entry* hashedEntry = fHashTable[hashIdx]; 107779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) { 1080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != hashedEntry->fProgram); 109779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = hashedEntry; 110779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 111779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 112779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int entryIdx; 113779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL == entry) { 114779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entryIdx = this->search(desc); 115779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (entryIdx >= 0) { 116779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = fEntries[entryIdx]; 117779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#ifdef PROGRAM_CACHE_STATS 118779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger ++fHashMisses; 119779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif 120779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 121779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 122779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == entry) { 124779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // We have a cache miss 125096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef PROGRAM_CACHE_STATS 126096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ++fCacheMisses; 127096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 1280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLProgram* program = GrGLProgram::Create(fGpu, desc, colorStages, coverageStages); 129779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (NULL == program) { 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 132779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int purgeIdx = 0; 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fCount < kMaxEntries) { 134779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = SkNEW(Entry); 135779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = fCount++; 136779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[purgeIdx] = entry; 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 1380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fCount == kMaxEntries); 139779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = 0; 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 1; i < kMaxEntries; ++i) { 141779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { 142779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger purgeIdx = i; 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 145779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry = fEntries[purgeIdx]; 146779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1); 147779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (fHashTable[purgedHashIdx] == entry) { 148779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[purgedHashIdx] = NULL; 149779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 1510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fEntries[purgeIdx] == entry); 152779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entry->fProgram.reset(program); 153779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // We need to shift fEntries around so that the entry currently at purgeIdx is placed 154779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). 155779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger entryIdx = ~entryIdx; 156779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (entryIdx < purgeIdx) { 157779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // Let E and P be the entries at index entryIdx and purgeIdx, respectively. 158779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // If the entries array looks like this: 159779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaEbbbbbPccccc 160779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // we rearrange it to look like this: 161779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaPEbbbbbccccc 162779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); 163779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); 164779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[entryIdx] = entry; 165779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } else if (purgeIdx < entryIdx) { 166779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // If the entries array looks like this: 167779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaaPbbbbbEccccc 168779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // we rearrange it to look like this: 169779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger // aaaabbbbbPEccccc 170779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); 171779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); 172779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[entryIdx - 1] = entry; 173779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 1740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef SK_DEBUG 1750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[0]->fProgram.get()); 176779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger for (int i = 0; i < fCount - 1; ++i) { 1770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != fEntries[i + 1]->fProgram.get()); 178779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc(); 179779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); 1800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(GrGLProgramDesc::Less(a, b)); 1810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!GrGLProgramDesc::Less(b, a)); 182779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger } 183779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 186779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fHashTable[hashIdx] = entry; 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fLRUStamp = fCurrLRUStamp; 188779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger 189779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger if (SK_MaxU32 == fCurrLRUStamp) { 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // wrap around! just trash our LRU, one time hit. 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < fCount; ++i) { 192779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger fEntries[i]->fLRUStamp = 0; 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ++fCurrLRUStamp; 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return entry->fProgram; 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////// 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGpuGL::abandonResources(){ 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::abandonResources(); 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fProgramCache->abandon(); 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHWProgramID = 0; 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////// 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrDrawState& drawState = this->getDrawState(); 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 214096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. 2150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != drawState.getRenderTarget()); 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 217096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (kStencilPath_DrawType == type) { 2180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 2190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkISize size; 2200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger size.set(rt->width(), rt->height()); 2210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); 222096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushMiscFixedFunctionState(); 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrBlendCoeff srcCoeff; 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrBlendCoeff dstCoeff; 227096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); 228096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkSTArray<8, const GrEffectStage*, true> colorStages; 23358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkSTArray<8, const GrEffectStage*, true> coverageStages; 2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLProgramDesc desc; 2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLProgramDesc::Build(this->getDrawState(), 236096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger kDrawPoints_DrawType == type, 237096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger blendOpts, 238096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger srcCoeff, 239096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger dstCoeff, 240096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this, 2417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger dstCopy, 24258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &colorStages, 24358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &coverageStages, 244096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger &desc); 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger fCurrentProgram.reset(fProgramCache->getProgram(desc, 24758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger colorStages.begin(), 24858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger coverageStages.begin())); 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == fCurrentProgram.get()) { 2500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDEBUGFAIL("Failed to create program!"); 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 2540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(kDrawPath_DrawType != type || !fCurrentProgram->hasVertexShader()); 2550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCurrentProgram.get()->ref(); 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 258096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLuint programID = fCurrentProgram->programID(); 259096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fHWProgramID != programID) { 260096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GL_CALL(UseProgram(programID)); 261096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fHWProgramID = programID; 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 263096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fCurrentProgram->setData(blendOpts, 26858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger colorStages.begin(), 26958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger coverageStages.begin(), 27058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger dstCopy, 27158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger &fSharedGLProgramState); 27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushStencil(type); 27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushScissor(); 27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushAAState(type); 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkIRect* devRect = NULL; 27858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkIRect devClipBounds; 27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (drawState.isClipState()) { 280d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); 28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru devRect = &devClipBounds; 28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // This must come after textures are flushed because a texture may need 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to be msaa-resolved (which will modify bound FBO state). 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->flushRenderTarget(devRect); 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 290096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergervoid GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 292910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger GrGLsizei stride = static_cast<GrGLsizei>(this->getDrawState().getVertexSize()); 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger size_t vertexOffsetInBytes = stride * info.startVertex(); 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const GeometryPoolState& geoPoolState = this->getGeomPoolState(); 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 298096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLVertexBuffer* vbuf; 299096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger switch (this->getGeomSrc().fVertexSrc) { 300096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kBuffer_GeometrySrcType: 301096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; 302096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 303096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kArray_GeometrySrcType: 304096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kReserved_GeometrySrcType: 305096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this->finalizeReservedVertices(); 306096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize; 307096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; 308096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 309096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger default: 310096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vbuf = NULL; // suppress warning 311096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrCrash("Unknown geometry src type!"); 31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != vbuf); 3150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!vbuf->isLocked()); 316096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger vertexOffsetInBytes += vbuf->baseOffset(); 317096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 318096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLIndexBuffer* ibuf = NULL; 319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (info.isIndexed()) { 3200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != indexOffsetInBytes); 321096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 322096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger switch (this->getGeomSrc().fIndexSrc) { 323096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kBuffer_GeometrySrcType: 324096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes = 0; 325096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; 326096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 327096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kArray_GeometrySrcType: 328096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger case kReserved_GeometrySrcType: 329096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this->finalizeReservedIndices(); 330096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); 331096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; 332096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 333096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger default: 334096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger ibuf = NULL; // suppress warning 335096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrCrash("Unknown geometry src type!"); 33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(NULL != ibuf); 3390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!ibuf->isLocked()); 340096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *indexOffsetInBytes += ibuf->baseOffset(); 34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 342096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GrGLAttribArrayState* attribState = 343096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); 344096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 3450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!fCurrentProgram->hasVertexShader()) { 3460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int posIdx = this->getDrawState().positionAttributeIndex(); 3470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrVertexAttrib* vertexArray = this->getDrawState().getVertexAttribs() + posIdx; 3480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrVertexAttribType vertexArrayType = vertexArray->fType; 3490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(!GrGLAttribTypeToLayout(vertexArrayType).fNormalized); 3500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(GrGLAttribTypeToLayout(vertexArrayType).fCount == 2); 3510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->setFixedFunctionVertexArray(this, 3520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vbuf, 3530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 2, 3540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(vertexArrayType).fType, 3550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger stride, 3560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger reinterpret_cast<GrGLvoid*>( 3570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexOffsetInBytes + vertexArray->fOffset)); 3580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->disableUnusedArrays(this, 0, true); 3590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } else { 3600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger uint32_t usedAttribArraysMask = 0; 3610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); 3620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger int vertexAttribCount = this->getDrawState().getVertexAttribCount(); 3630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; 3640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger ++vertexAttribIndex, ++vertexAttrib) { 3650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 3660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger usedAttribArraysMask |= (1 << vertexAttribIndex); 3670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrVertexAttribType attribType = vertexAttrib->fType; 3680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->set(this, 3690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexAttribIndex, 3700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vbuf, 3710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fCount, 3720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fType, 3730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrGLAttribTypeToLayout(attribType).fNormalized, 3740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger stride, 3750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger reinterpret_cast<GrGLvoid*>( 3760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger vertexOffsetInBytes + vertexAttrib->fOffset)); 3770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger attribState->disableUnusedArrays(this, usedAttribArraysMask, false); 3800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 382