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