13f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com/*
23f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Copyright 2011 Google Inc.
33f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com *
43f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
53f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * found in the LICENSE file.
63f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com */
73f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
856a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com#include "GrGpuGL.h"
93f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
103829e11b4220c9dd4b23985111deefa061716435bsalomon@google.com#include "GrEffect.h"
11aab3f0a5176fa13f1f0452386651dc5c8676ba68bsalomon@google.com#include "GrGLEffect.h"
1266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com#include "SkTSearch.h"
133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
14e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle;
15e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.comstatic const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
16e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com
1766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.comstruct GrGpuGL::ProgramCache::Entry {
1866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    SK_DECLARE_INST_COUNT_ROOT(Entry);
1966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    Entry() : fProgram(NULL), fLRUStamp(0) {}
2066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
2166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    SkAutoTUnref<GrGLProgram>   fProgram;
2266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    unsigned int                fLRUStamp;
2366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com};
2466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
2566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.comSK_DEFINE_INST_COUNT(GrGpuGL::ProgramCache::Entry);
2666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
2766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.comstruct GrGpuGL::ProgramCache::ProgDescLess {
2866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    bool operator() (const GrGLProgramDesc& desc, const Entry* entry) {
2966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != entry->fProgram.get());
3066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc());
3166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
3266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
3366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    bool operator() (const Entry* entry, const GrGLProgramDesc& desc) {
3466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != entry->fProgram.get());
3566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc);
3666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
3766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com};
383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
39860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.comGrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl)
4028cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    : fCount(0)
4128cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    , fCurrLRUStamp(0)
42010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com    , fGL(gl)
43c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#ifdef PROGRAM_CACHE_STATS
44c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    , fTotalRequests(0)
45c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    , fCacheMisses(0)
4666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    , fHashMisses(0)
47c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#endif
48c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com{
4966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    for (int i = 0; i < 1 << kHashBits; ++i) {
5066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        fHashTable[i] = NULL;
5166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
52c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com}
53c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com
54c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.comGrGpuGL::ProgramCache::~ProgramCache() {
5566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    for (int i = 0; i < fCount; ++i){
5666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        SkDELETE(fEntries[i]);
5766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
58c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    // dump stats
59c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#ifdef PROGRAM_CACHE_STATS
60c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    SkDebugf("--- Program Cache ---\n");
61c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    SkDebugf("Total requests: %d\n", fTotalRequests);
62c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    SkDebugf("Cache misses: %d\n", fCacheMisses);
6366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
6466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com                                        100.f * fCacheMisses / fTotalRequests :
6566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com                                        0.f);
6666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    int cacheHits = fTotalRequests - fCacheMisses;
6766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f);
68c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    SkDebugf("---------------------\n");
69c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#endif
7028cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com}
713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
72cc9477a26fc4998e1f2094d563efd322da1e49aabsalomon@google.comvoid GrGpuGL::ProgramCache::abandon() {
7328cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    for (int i = 0; i < fCount; ++i) {
7466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != fEntries[i]->fProgram.get());
7566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        fEntries[i]->fProgram->abandon();
7666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        fEntries[i]->fProgram.reset(NULL);
773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
7828cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    fCount = 0;
7928cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com}
803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.comint GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
8266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    ProgDescLess less;
8366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less);
8466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com}
8566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
8684dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.comGrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
87388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                               const GrEffectStage* colorStages[],
88388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                               const GrEffectStage* coverageStages[]) {
89c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#ifdef PROGRAM_CACHE_STATS
90c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com    ++fTotalRequests;
91c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#endif
9285f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com
9366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    Entry* entry = NULL;
9466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
9566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    uint32_t hashIdx = desc.getChecksum();
9666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    hashIdx ^= hashIdx >> 16;
9766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (kHashBits <= 8) {
9866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        hashIdx ^= hashIdx >> 8;
9966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
10066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    hashIdx &=((1 << kHashBits) - 1);
10166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    Entry* hashedEntry = fHashTable[hashIdx];
10266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) {
10366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != hashedEntry->fProgram);
10466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        entry = hashedEntry;
10566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
10666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
10766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    int entryIdx;
10866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (NULL == entry) {
10966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        entryIdx = this->search(desc);
11066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        if (entryIdx >= 0) {
11166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            entry = fEntries[entryIdx];
11266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com#ifdef PROGRAM_CACHE_STATS
11366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            ++fHashMisses;
11466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com#endif
11566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        }
11666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    }
11766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
11828cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    if (NULL == entry) {
11966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        // We have a cache miss
120c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#ifdef PROGRAM_CACHE_STATS
121c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com        ++fCacheMisses;
122c8fce3912f50a1c3c08d25503649d7c0387bc994jvanverth@google.com#endif
123388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com        GrGLProgram* program = GrGLProgram::Create(fGL, desc, colorStages, coverageStages);
12466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        if (NULL == program) {
12528cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com            return NULL;
12628cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com        }
12766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        int purgeIdx = 0;
12828cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com        if (fCount < kMaxEntries) {
12966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            entry = SkNEW(Entry);
13066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            purgeIdx = fCount++;
13166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            fEntries[purgeIdx] = entry;
13228cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com        } else {
13366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            GrAssert(fCount == kMaxEntries);
13466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            purgeIdx = 0;
13528cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com            for (int i = 1; i < kMaxEntries; ++i) {
13666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com                if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) {
13766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com                    purgeIdx = i;
1383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                }
1393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            }
14066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            entry = fEntries[purgeIdx];
14166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1);
14266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            if (fHashTable[purgedHashIdx] == entry) {
14366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com                fHashTable[purgedHashIdx] = NULL;
14466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            }
1453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
14666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(fEntries[purgeIdx] == entry);
14766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        entry->fProgram.reset(program);
148286ff824839d026ef0c33e6e18e3747b561d8f91skia.committer@gmail.com        // We need to shift fEntries around so that the entry currently at purgeIdx is placed
14966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor).
15066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        entryIdx = ~entryIdx;
15166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        if (entryIdx < purgeIdx) {
15266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //  Let E and P be the entries at index entryIdx and purgeIdx, respectively.
15366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //  If the entries array looks like this:
15466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //       aaaaEbbbbbPccccc
15566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //  we rearrange it to look like this:
15666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //       aaaaPEbbbbbccccc
15766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*);
15866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize);
15966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            fEntries[entryIdx] = entry;
16066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        } else if (purgeIdx < entryIdx) {
16166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //  If the entries array looks like this:
16266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //       aaaaPbbbbbEccccc
16366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //  we rearrange it to look like this:
16466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            //       aaaabbbbbPEccccc
16566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*);
16666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize);
16766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            fEntries[entryIdx - 1] = entry;
16866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        }
16966307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com#if GR_DEBUG
17066307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != fEntries[0]->fProgram.get());
17166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        for (int i = 0; i < fCount - 1; ++i) {
17266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            GrAssert(NULL != fEntries[i + 1]->fProgram.get());
17366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc();
17466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc();
17566307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            GrAssert(GrGLProgramDesc::Less(a, b));
17666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            GrAssert(!GrGLProgramDesc::Less(b, a));
17766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        }
17866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com#endif
17928cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    }
1803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
18166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    fHashTable[hashIdx] = entry;
18228cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    entry->fLRUStamp = fCurrLRUStamp;
18366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
18466307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (SK_MaxU32 == fCurrLRUStamp) {
18528cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com        // wrap around! just trash our LRU, one time hit.
18628cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com        for (int i = 0; i < fCount; ++i) {
18766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com            fEntries[i]->fLRUStamp = 0;
1883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
1893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
19028cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com    ++fCurrLRUStamp;
19185f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com    return entry->fProgram;
19228cf5a7c321f9a60e0fd8029afe3fe8aff0da542bsalomon@google.com}
1933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
1953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
19656a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.comvoid GrGpuGL::abandonResources(){
19756a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com    INHERITED::abandonResources();
19856a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com    fProgramCache->abandon();
19956a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com    fHWProgramID = 0;
20056a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com}
20156a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com
20256a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
20356a27453dc4275cfafe261230e4fdf06839c0fafbsalomon@google.com
2043f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
2053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
206f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.comvoid GrGpuGL::flushPathStencilMatrix() {
207f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix();
208f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
209f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    SkISize size;
210f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    size.set(rt->width(), rt->height());
211a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com    const SkMatrix& vm = this->getDrawState().getViewMatrix();
212c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com
213f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    if (fHWPathStencilMatrixState.fRenderTargetOrigin != rt->origin() ||
214b68ef964307b5d33432cd402a7c0b74272e8f9fecommit-bot@chromium.org        !fHWPathStencilMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) ||
215f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        fHWPathStencilMatrixState.fRenderTargetSize!= size) {
216f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        // rescale the coords from skia's "device" coords to GL's normalized coords,
217f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        // and perform a y-flip if required.
218a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com        SkMatrix m;
219e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
220f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
221f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            m.postTranslate(-SK_Scalar1, SK_Scalar1);
222e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        } else {
223f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height());
224f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            m.postTranslate(-SK_Scalar1, -SK_Scalar1);
225e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        }
226f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        m.preConcat(vm);
227c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com
228f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        // GL wants a column-major 4x4.
229f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        GrGLfloat mv[]  = {
230f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            // col 0
231a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMScaleX]),
232a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMSkewY]),
233f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            0,
234a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMPersp0]),
235f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com
236f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            // col 1
237a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMSkewX]),
238a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMScaleY]),
239f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            0,
240a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMPersp1]),
241f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com
242f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            // col 2
243f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            0, 0, 0, 0,
244f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com
245f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            // col3
246a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMTransX]),
247a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMTransY]),
248f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            0.0f,
249a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkScalarToFloat(m[SkMatrix::kMPersp2])
250c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com        };
251f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        GL_CALL(MatrixMode(GR_GL_PROJECTION));
252f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        GL_CALL(LoadMatrixf(mv));
253f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        fHWPathStencilMatrixState.fViewMatrix = vm;
254f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        fHWPathStencilMatrixState.fRenderTargetSize = size;
255f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        fHWPathStencilMatrixState.fRenderTargetOrigin = rt->origin();
2563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
25903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.combool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
260c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    const GrDrawState& drawState = this->getDrawState();
261c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com
262f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
2630e74750f8dd92ba54adc0e63539ad01fe584d7a4bsalomon@google.com    GrAssert(NULL != drawState.getRenderTarget());
2640e74750f8dd92ba54adc0e63539ad01fe584d7a4bsalomon@google.com
265f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    if (kStencilPath_DrawType == type) {
266f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        this->flushPathStencilMatrix();
267f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com    } else {
2688dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        this->flushMiscFixedFunctionState();
2693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2708dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        GrBlendCoeff srcCoeff;
2718dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        GrBlendCoeff dstCoeff;
272f1a7c7962e72d83a3bf733d2c39571b513b2df32bsalomon@google.com        GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff);
273f1a7c7962e72d83a3bf733d2c39571b513b2df32bsalomon@google.com        if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) {
2748dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com            return false;
2758dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        }
2763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
277388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com        SkSTArray<8, const GrEffectStage*, true> colorStages;
278388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com        SkSTArray<8, const GrEffectStage*, true> coverageStages;
27984dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.com        GrGLProgramDesc desc;
28084dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.com        GrGLProgramDesc::Build(this->getDrawState(),
28149467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               kDrawPoints_DrawType == type,
28249467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               blendOpts,
28349467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               srcCoeff,
28449467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               dstCoeff,
28549467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               this,
28603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                               dstCopy,
287388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                               &colorStages,
288388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                               &coverageStages,
28949467dd13b26cc2f1f3fc3e2c8dfd432af04a8eabsalomon@google.com                               &desc);
29085f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com
291388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com        fCurrentProgram.reset(fProgramCache->getProgram(desc,
292388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                                        colorStages.begin(),
293388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                                        coverageStages.begin()));
29485f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com        if (NULL == fCurrentProgram.get()) {
2958dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com            GrAssert(!"Failed to create program!");
2968dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com            return false;
2978dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        }
29885f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com        fCurrentProgram.get()->ref();
29921b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com
300f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        GrGLuint programID = fCurrentProgram->programID();
301f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com        if (fHWProgramID != programID) {
302f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            GL_CALL(UseProgram(programID));
303f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com            fHWProgramID = programID;
3048dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        }
305f2d487999e61c562fafa76d8d597070636b2d1a8bsalomon@google.com
30685f928e239fa940a6089adad9f68438aa373b2b0bsalomon@google.com        fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
3078dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com        this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
3088dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com
309388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com        fCurrentProgram->setData(this,
310388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                 blendOpts,
311388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                 colorStages.begin(),
312388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                 coverageStages.begin(),
313388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                 dstCopy,
314388fc3191dc73013bfe66564297ffa6b6df8382bbsalomon@google.com                                 &fSharedGLProgramState);
3153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3168dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com    this->flushStencil(type);
31785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com    this->flushScissor();
3188dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com    this->flushAAState(type);
31921b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com
320a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    SkIRect* devRect = NULL;
321a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    SkIRect devClipBounds;
32215e7ae449c45978bc7ed7aba427369e4f78bc6derobertphillips@google.com    if (drawState.isClipState()) {
3238b62219b7c4b5c543eb9cdb7da38184232c59812bsalomon@google.com        this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
324b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com        devRect = &devClipBounds;
32521b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com    }
32621b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com    // This must come after textures are flushed because a texture may need
32721b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com    // to be msaa-resolved (which will modify bound FBO state).
328b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    this->flushRenderTarget(devRect);
32921b8816f58ad7383f7b98d92c6b41db665dec881bsalomon@google.com
3303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return true;
3313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
3323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
333b8b37ab1327695d35b9b736440b34ebba67d264fbsalomon@google.comvoid GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
3343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
335768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    GrGLsizei stride = this->getDrawState().getVertexSize();
336b8b37ab1327695d35b9b736440b34ebba67d264fbsalomon@google.com
3373f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    size_t vertexOffsetInBytes = stride * info.startVertex();
3383f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3393f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    const GeometryPoolState& geoPoolState = this->getGeomPoolState();
3403f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3413f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrGLVertexBuffer* vbuf;
3423f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    switch (this->getGeomSrc().fVertexSrc) {
3433f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kBuffer_GeometrySrcType:
3443f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
3453f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            break;
3463f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kArray_GeometrySrcType:
3473f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kReserved_GeometrySrcType:
3483f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            this->finalizeReservedVertices();
3493f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize;
3503f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
3513f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            break;
3523f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        default:
3533f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            vbuf = NULL; // suppress warning
3543f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            GrCrash("Unknown geometry src type!");
3553f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
3563f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3573f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrAssert(NULL != vbuf);
3583f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrAssert(!vbuf->isLocked());
3593f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    vertexOffsetInBytes += vbuf->baseOffset();
3603f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3613f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrGLIndexBuffer* ibuf = NULL;
3623f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (info.isIndexed()) {
3633f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GrAssert(NULL != indexOffsetInBytes);
3643f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3653f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        switch (this->getGeomSrc().fIndexSrc) {
3663f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kBuffer_GeometrySrcType:
3673f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            *indexOffsetInBytes = 0;
3683f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
3693f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            break;
3703f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kArray_GeometrySrcType:
3713f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        case kReserved_GeometrySrcType:
3723f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            this->finalizeReservedIndices();
3733f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
3743f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
3753f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            break;
3763f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        default:
3773f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            ibuf = NULL; // suppress warning
3783f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            GrCrash("Unknown geometry src type!");
3793f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        }
3803f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
3813f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GrAssert(NULL != ibuf);
3823f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GrAssert(!ibuf->isLocked());
3833f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        *indexOffsetInBytes += ibuf->baseOffset();
3843f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
3853f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrGLAttribArrayState* attribState =
3863f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
387b8b37ab1327695d35b9b736440b34ebba67d264fbsalomon@google.com
388768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    uint32_t usedAttribArraysMask = 0;
389768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
390768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    int vertexAttribCount = this->getDrawState().getVertexAttribCount();
391bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
392768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com         ++vertexAttribIndex, ++vertexAttrib) {
3933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
394768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com        usedAttribArraysMask |= (1 << vertexAttribIndex);
395768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com        GrVertexAttribType attribType = vertexAttrib->fType;
3963f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        attribState->set(this,
3973f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                         vertexAttribIndex,
3983f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                         vbuf,
39984dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.com                         GrGLAttribTypeToLayout(attribType).fCount,
40084dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.com                         GrGLAttribTypeToLayout(attribType).fType,
40184dd5d4d09fa17feaea61280eea8fa12f429014absalomon@google.com                         GrGLAttribTypeToLayout(attribType).fNormalized,
4023f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                         stride,
4033f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                         reinterpret_cast<GrGLvoid*>(
4043f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                         vertexOffsetInBytes + vertexAttrib->fOffset));
4053f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
4063f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
4073f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    attribState->disableUnusedAttribArrays(this, usedAttribArraysMask);
4083f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
409