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