Home | History | Annotate | Download | only in OpenglCodecCommon
      1 /*
      2 * Copyright (C) 2011 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include "GLSharedGroup.h"
     18 
     19 /**** KeyedVector utilities ****/
     20 
     21 template <typename T>
     22 static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) {
     23     for (size_t i = 0; i < v.size(); i++)
     24         delete v.valueAt(i);
     25     v.clear();
     26 }
     27 
     28 /**** BufferData ****/
     29 
     30 BufferData::BufferData() : m_size(0), m_usage(0), m_mapped(false) {};
     31 BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size), m_usage(0), m_mapped(false)
     32 {
     33     void * buffer = NULL;
     34     if (size>0) buffer = m_fixedBuffer.alloc(size);
     35     if (data) memcpy(buffer, data, size);
     36 }
     37 
     38 /**** ProgramData ****/
     39 ProgramData::ProgramData() : m_numIndexes(0),
     40                              m_initialized(false),
     41                              m_locShiftWAR(false)
     42 {
     43     m_Indexes = NULL;
     44 }
     45 
     46 void ProgramData::initProgramData(GLuint numIndexes)
     47 {
     48     m_initialized = true;
     49     m_numIndexes = numIndexes;
     50     delete[] m_Indexes;
     51     m_Indexes = new IndexInfo[numIndexes];
     52     m_locShiftWAR = false;
     53 }
     54 
     55 bool ProgramData::isInitialized()
     56 {
     57     return m_initialized;
     58 }
     59 
     60 ProgramData::~ProgramData()
     61 {
     62     delete[] m_Indexes;
     63     m_Indexes = NULL;
     64 }
     65 
     66 void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type)
     67 {
     68     if (index>=m_numIndexes)
     69         return;
     70     m_Indexes[index].base = base;
     71     m_Indexes[index].size = size;
     72     m_Indexes[index].type = type;
     73     if (index > 0) {
     74         m_Indexes[index].appBase = m_Indexes[index-1].appBase +
     75                                    m_Indexes[index-1].size;
     76     }
     77     else {
     78         m_Indexes[index].appBase = 0;
     79     }
     80     m_Indexes[index].hostLocsPerElement = 1;
     81     m_Indexes[index].flags = 0;
     82     m_Indexes[index].samplerValue = 0;
     83 }
     84 
     85 void ProgramData::setIndexFlags(GLuint index, GLuint flags)
     86 {
     87     if (index >= m_numIndexes)
     88         return;
     89     m_Indexes[index].flags |= flags;
     90 }
     91 
     92 GLuint ProgramData::getIndexForLocation(GLint location)
     93 {
     94     GLuint index = m_numIndexes;
     95     GLint minDist = -1;
     96     for (GLuint i=0;i<m_numIndexes;++i)
     97     {
     98         GLint dist = location - m_Indexes[i].base;
     99         if (dist >= 0 &&
    100             (minDist < 0 || dist < minDist)) {
    101             index = i;
    102             minDist = dist;
    103         }
    104     }
    105     return index;
    106 }
    107 
    108 GLenum ProgramData::getTypeForLocation(GLint location)
    109 {
    110     GLuint index = getIndexForLocation(location);
    111     if (index<m_numIndexes) {
    112         return m_Indexes[index].type;
    113     }
    114     return 0;
    115 }
    116 
    117 void ProgramData::setupLocationShiftWAR()
    118 {
    119     m_locShiftWAR = false;
    120     for (GLuint i=0; i<m_numIndexes; i++) {
    121         if (0 != (m_Indexes[i].base & 0xffff)) {
    122             return;
    123         }
    124     }
    125     // if we have one uniform at location 0, we do not need the WAR.
    126     if (m_numIndexes > 1) {
    127         m_locShiftWAR = true;
    128     }
    129 }
    130 
    131 GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex)
    132 {
    133     if (!m_locShiftWAR) return hostLoc;
    134 
    135     GLuint index = getIndexForLocation(hostLoc);
    136     if (index<m_numIndexes) {
    137         if (arrIndex > 0) {
    138             m_Indexes[index].hostLocsPerElement =
    139                               (hostLoc - m_Indexes[index].base) / arrIndex;
    140         }
    141         return m_Indexes[index].appBase + arrIndex;
    142     }
    143     return -1;
    144 }
    145 
    146 GLint ProgramData::locationWARAppToHost(GLint appLoc)
    147 {
    148     if (!m_locShiftWAR) return appLoc;
    149 
    150     for(GLuint i=0; i<m_numIndexes; i++) {
    151         GLint elemIndex = appLoc - m_Indexes[i].appBase;
    152         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
    153             return m_Indexes[i].base +
    154                    elemIndex * m_Indexes[i].hostLocsPerElement;
    155         }
    156     }
    157     return -1;
    158 }
    159 
    160 GLint ProgramData::getNextSamplerUniform(GLint index, GLint* val, GLenum* target)
    161 {
    162     for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {
    163         if (m_Indexes[i].type == GL_SAMPLER_2D) {
    164             if (val) *val = m_Indexes[i].samplerValue;
    165             if (target) {
    166                 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
    167                     *target = GL_TEXTURE_EXTERNAL_OES;
    168                 } else {
    169                     *target = GL_TEXTURE_2D;
    170                 }
    171             }
    172             return i;
    173         }
    174     }
    175     return -1;
    176 }
    177 
    178 bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target)
    179 {
    180     for (GLuint i = 0; i < m_numIndexes; i++) {
    181         GLint elemIndex = appLoc - m_Indexes[i].appBase;
    182         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
    183             if (m_Indexes[i].type == GL_TEXTURE_2D) {
    184                 m_Indexes[i].samplerValue = val;
    185                 if (target) {
    186                     if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
    187                         *target = GL_TEXTURE_EXTERNAL_OES;
    188                     } else {
    189                         *target = GL_TEXTURE_2D;
    190                     }
    191                 }
    192                 return true;
    193             }
    194         }
    195     }
    196     return false;
    197 }
    198 
    199 bool ProgramData::attachShader(GLuint shader)
    200 {
    201     size_t n = m_shaders.size();
    202     for (size_t i = 0; i < n; i++) {
    203         if (m_shaders[i] == shader) {
    204             return false;
    205         }
    206     }
    207     // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
    208     // due to the default parameters. This is the desired insertAt() overload.
    209     m_shaders.insertAt(shader, m_shaders.size(), 1);
    210     return true;
    211 }
    212 
    213 bool ProgramData::detachShader(GLuint shader)
    214 {
    215     size_t n = m_shaders.size();
    216     for (size_t i = 0; i < n; i++) {
    217         if (m_shaders[i] == shader) {
    218             m_shaders.removeAt(i);
    219             return true;
    220         }
    221     }
    222     return false;
    223 }
    224 
    225 /***** GLSharedGroup ****/
    226 
    227 GLSharedGroup::GLSharedGroup() :
    228     m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
    229     m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
    230     m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL)),
    231     m_shaderPrograms(android::DefaultKeyedVector<GLuint, ShaderProgramData*>(NULL))
    232 {
    233 }
    234 
    235 GLSharedGroup::~GLSharedGroup()
    236 {
    237     m_buffers.clear();
    238     m_programs.clear();
    239     clearObjectMap(m_buffers);
    240     clearObjectMap(m_programs);
    241     clearObjectMap(m_shaders);
    242     clearObjectMap(m_shaderPrograms);
    243 }
    244 
    245 bool GLSharedGroup::isShaderOrProgramObject(GLuint obj)
    246 {
    247     android::AutoMutex _lock(m_lock);
    248     return ((m_shaders.valueFor(obj)!=NULL) ||
    249             (m_programs.valueFor(obj)!=NULL) ||
    250             (m_shaderPrograms.valueFor(m_shaderProgramIdMap[obj]) !=NULL));
    251 }
    252 
    253 BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
    254 {
    255     android::AutoMutex _lock(m_lock);
    256     return m_buffers.valueFor(bufferId);
    257 }
    258 
    259 SharedTextureDataMap* GLSharedGroup::getTextureData() {
    260     return &m_textureRecs;
    261 }
    262 
    263 void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
    264 {
    265     android::AutoMutex _lock(m_lock);
    266     m_buffers.add(bufferId, new BufferData(size, data));
    267 }
    268 
    269 void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
    270 {
    271     android::AutoMutex _lock(m_lock);
    272     ssize_t idx = m_buffers.indexOfKey(bufferId);
    273     if (idx >= 0) {
    274         delete m_buffers.valueAt(idx);
    275         m_buffers.editValueAt(idx) = new BufferData(size, data);
    276     } else {
    277         m_buffers.add(bufferId, new BufferData(size, data));
    278     }
    279 }
    280 
    281 void GLSharedGroup::setBufferUsage(GLuint bufferId, GLenum usage) {
    282     android::AutoMutex _lock(m_lock);
    283     ssize_t idx = m_buffers.indexOfKey(bufferId);
    284     if (idx >= 0) {
    285         m_buffers.editValueAt(idx)->m_usage = usage;
    286     }
    287 }
    288 
    289 void GLSharedGroup::setBufferMapped(GLuint bufferId, bool mapped) {
    290     BufferData * buf = m_buffers.valueFor(bufferId);
    291     if (!buf) return;
    292     buf->m_mapped = mapped;
    293 }
    294 
    295 GLenum GLSharedGroup::getBufferUsage(GLuint bufferId) {
    296     BufferData * buf = m_buffers.valueFor(bufferId);
    297     if (!buf) return 0;
    298     return buf->m_usage;
    299 }
    300 
    301 bool GLSharedGroup::isBufferMapped(GLuint bufferId) {
    302     BufferData * buf = m_buffers.valueFor(bufferId);
    303     if (!buf) return false;
    304     return buf->m_mapped;
    305 }
    306 
    307 GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
    308 {
    309     android::AutoMutex _lock(m_lock);
    310     BufferData * buf = m_buffers.valueFor(bufferId);
    311     if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
    312 
    313     //it's safe to update now
    314     memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
    315 
    316     buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
    317     return GL_NO_ERROR;
    318 }
    319 
    320 void GLSharedGroup::deleteBufferData(GLuint bufferId)
    321 {
    322     android::AutoMutex _lock(m_lock);
    323     ssize_t idx = m_buffers.indexOfKey(bufferId);
    324     if (idx >= 0) {
    325         delete m_buffers.valueAt(idx);
    326         m_buffers.removeItemsAt(idx);
    327     }
    328 }
    329 
    330 void GLSharedGroup::addProgramData(GLuint program)
    331 {
    332     android::AutoMutex _lock(m_lock);
    333     ProgramData *pData = m_programs.valueFor(program);
    334     if (pData)
    335     {
    336         m_programs.removeItem(program);
    337         delete pData;
    338     }
    339 
    340     m_programs.add(program,new ProgramData());
    341 }
    342 
    343 void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
    344 {
    345     android::AutoMutex _lock(m_lock);
    346     ProgramData *pData = m_programs.valueFor(program);
    347     if (pData)
    348     {
    349         pData->initProgramData(numIndexes);
    350     }
    351 }
    352 
    353 bool GLSharedGroup::isProgramInitialized(GLuint program)
    354 {
    355     android::AutoMutex _lock(m_lock);
    356     ProgramData* pData = m_programs.valueFor(program);
    357     if (pData)
    358     {
    359         return pData->isInitialized();
    360     }
    361     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
    362     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    363     if (spData) {
    364         return spData->programData->isInitialized();
    365     }
    366     return false;
    367 }
    368 
    369 void GLSharedGroup::deleteProgramData(GLuint program)
    370 {
    371     android::AutoMutex _lock(m_lock);
    372     ProgramData *pData = m_programs.valueFor(program);
    373     if (pData) {
    374         delete pData;
    375     }
    376     m_programs.removeItem(program);
    377 
    378     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return;
    379     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    380     if (spData) {
    381         delete spData;
    382     }
    383     m_shaderPrograms.removeItem(m_shaderProgramIdMap[program]);
    384     m_shaderProgramIdMap.erase(program);
    385 }
    386 
    387 // No such thing for separable shader programs.
    388 void GLSharedGroup::attachShader(GLuint program, GLuint shader)
    389 {
    390     android::AutoMutex _lock(m_lock);
    391     ProgramData* programData = m_programs.valueFor(program);
    392     ssize_t idx = m_shaders.indexOfKey(shader);
    393     if (programData && idx >= 0) {
    394         if (programData->attachShader(shader)) {
    395             refShaderDataLocked(idx);
    396         }
    397     }
    398 }
    399 
    400 void GLSharedGroup::detachShader(GLuint program, GLuint shader)
    401 {
    402     android::AutoMutex _lock(m_lock);
    403     ProgramData* programData = m_programs.valueFor(program);
    404     ssize_t idx = m_shaders.indexOfKey(shader);
    405     if (programData && idx >= 0) {
    406         if (programData->detachShader(shader)) {
    407             unrefShaderDataLocked(idx);
    408         }
    409     }
    410 }
    411 
    412 // Not needed/used for separate shader programs.
    413 void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
    414 {
    415     android::AutoMutex _lock(m_lock);
    416     ProgramData* pData = m_programs.valueFor(program);
    417     if (pData)
    418     {
    419         pData->setIndexInfo(index,base,size,type);
    420 
    421         if (type == GL_SAMPLER_2D) {
    422             size_t n = pData->getNumShaders();
    423             for (size_t i = 0; i < n; i++) {
    424                 GLuint shaderId = pData->getShader(i);
    425                 ShaderData* shader = m_shaders.valueFor(shaderId);
    426                 if (!shader) continue;
    427                 ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
    428                 ShaderData::StringList::iterator nameEnd  = shader->samplerExternalNames.end();
    429                 while (nameIter != nameEnd) {
    430                     if (*nameIter == name) {
    431                         pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
    432                         break;
    433                     }
    434                     ++nameIter;
    435                 }
    436             }
    437         }
    438     }
    439 }
    440 
    441 GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
    442 {
    443     android::AutoMutex _lock(m_lock);
    444     ProgramData* pData = m_programs.valueFor(program);
    445     GLenum type=0;
    446     if (pData) {
    447         type = pData->getTypeForLocation(location);
    448     }
    449     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return type;
    450     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    451     if (spData) {
    452         type = spData->programData->getTypeForLocation(location);
    453     }
    454     return type;
    455 }
    456 
    457 bool  GLSharedGroup::isProgram(GLuint program)
    458 {
    459     android::AutoMutex _lock(m_lock);
    460     ProgramData* pData = m_programs.valueFor(program);
    461     if (pData) return true;
    462     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
    463     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    464     if (spData) return true;
    465     return false;
    466 }
    467 
    468 void GLSharedGroup::setupLocationShiftWAR(GLuint program)
    469 {
    470     android::AutoMutex _lock(m_lock);
    471     ProgramData* pData = m_programs.valueFor(program);
    472     if (pData) pData->setupLocationShiftWAR();
    473 }
    474 
    475 GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
    476 {
    477     android::AutoMutex _lock(m_lock);
    478     ProgramData* pData = m_programs.valueFor(program);
    479     if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
    480     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return hostLoc;
    481     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    482     if (spData) return spData->programData->locationWARHostToApp(hostLoc, arrIndex);
    483     return hostLoc;
    484 }
    485 
    486 GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
    487 {
    488     android::AutoMutex _lock(m_lock);
    489     ProgramData* pData = m_programs.valueFor(program);
    490     if (pData) return pData->locationWARAppToHost(appLoc);
    491     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return appLoc;
    492     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    493     if (spData) return spData->programData->locationWARAppToHost(appLoc);
    494     return appLoc;
    495 }
    496 
    497 bool GLSharedGroup::needUniformLocationWAR(GLuint program)
    498 {
    499     android::AutoMutex _lock(m_lock);
    500     ProgramData* pData = m_programs.valueFor(program);
    501     if (pData) return pData->needUniformLocationWAR();
    502     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
    503     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    504     if (spData) return spData->programData->needUniformLocationWAR();
    505     return false;
    506 }
    507 
    508 GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
    509 {
    510     android::AutoMutex _lock(m_lock);
    511     ProgramData* pData = m_programs.valueFor(program);
    512     if (pData) return pData->getNextSamplerUniform(index, val, target);
    513     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return -1;
    514     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap.find(program)->second);
    515     if (spData) return spData->programData->getNextSamplerUniform(index, val, target);
    516     return -1;
    517 }
    518 
    519 bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
    520 {
    521     android::AutoMutex _lock(m_lock);
    522     ProgramData* pData = m_programs.valueFor(program);
    523     if (pData) return pData->setSamplerUniform(appLoc, val, target);
    524     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
    525     ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
    526     if (spData) return spData->programData->setSamplerUniform(appLoc, val, target);
    527     return false;
    528 }
    529 
    530 bool  GLSharedGroup::isShader(GLuint shader)
    531 {
    532     android::AutoMutex _lock(m_lock);
    533     ShaderData* pData = m_shaders.valueFor(shader);
    534     return (pData!=NULL);
    535 }
    536 
    537 bool GLSharedGroup::addShaderData(GLuint shader)
    538 {
    539     android::AutoMutex _lock(m_lock);
    540     ShaderData* data = new ShaderData;
    541     if (data) {
    542         if (m_shaders.add(shader, data) < 0) {
    543             delete data;
    544             data = NULL;
    545         }
    546         data->refcount = 1;
    547     }
    548     return data != NULL;
    549 }
    550 
    551 ShaderData* GLSharedGroup::getShaderData(GLuint shader)
    552 {
    553     android::AutoMutex _lock(m_lock);
    554     return m_shaders.valueFor(shader);
    555 }
    556 
    557 void GLSharedGroup::unrefShaderData(GLuint shader)
    558 {
    559     android::AutoMutex _lock(m_lock);
    560     ssize_t idx = m_shaders.indexOfKey(shader);
    561     if (idx >= 0) {
    562         unrefShaderDataLocked(idx);
    563     }
    564 }
    565 
    566 void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
    567 {
    568     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
    569     ShaderData* data = m_shaders.valueAt(shaderIdx);
    570     data->refcount++;
    571 }
    572 
    573 void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
    574 {
    575     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
    576     ShaderData* data = m_shaders.valueAt(shaderIdx);
    577     if (--data->refcount == 0) {
    578         delete data;
    579         m_shaders.removeItemsAt(shaderIdx);
    580     }
    581 }
    582 
    583 uint32_t GLSharedGroup::addNewShaderProgramData() {
    584     android::AutoMutex _lock(m_lock);
    585     ShaderProgramData* data = new ShaderProgramData;
    586     uint32_t currId = m_shaderProgramId;
    587     ALOGD("%s: new data %p id %u", __FUNCTION__, data, currId);
    588     m_shaderPrograms.add(currId, data);
    589     m_shaderProgramId++;
    590     return currId;
    591 }
    592 
    593 void GLSharedGroup::associateGLShaderProgram(GLuint shaderProgramName, uint32_t shaderProgramId) {
    594     android::AutoMutex _lock(m_lock);
    595     m_shaderProgramIdMap[shaderProgramName] = shaderProgramId;
    596 }
    597 
    598 ShaderProgramData* GLSharedGroup::getShaderProgramDataById(uint32_t id) {
    599     android::AutoMutex _lock(m_lock);
    600     ShaderProgramData* res = m_shaderPrograms.valueFor(id);
    601     ALOGD("%s: id=%u res=%p", __FUNCTION__, id, res);
    602     return res;
    603 }
    604 
    605 ShaderProgramData* GLSharedGroup::getShaderProgramData(GLuint shaderProgramName) {
    606     android::AutoMutex _lock(m_lock);
    607     return m_shaderPrograms.valueFor(m_shaderProgramIdMap[shaderProgramName]);
    608 }
    609 
    610 void GLSharedGroup::deleteShaderProgramDataById(uint32_t id) {
    611     android::AutoMutex _lock(m_lock);
    612     ShaderProgramData* data = m_shaderPrograms.valueFor(id);
    613     delete data;
    614     m_shaderPrograms.removeItemsAt(id);
    615 }
    616 
    617 
    618 void GLSharedGroup::deleteShaderProgramData(GLuint shaderProgramName) {
    619     android::AutoMutex _lock(m_lock);
    620     uint32_t id = m_shaderProgramIdMap[shaderProgramName];
    621     ShaderProgramData* data = m_shaderPrograms.valueFor(id);
    622     delete data;
    623     m_shaderPrograms.removeItemsAt(id);
    624     m_shaderProgramIdMap.erase(shaderProgramName);
    625 }
    626 
    627 void GLSharedGroup::initShaderProgramData(GLuint shaderProgram, GLuint numIndices) {
    628     ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    629     spData->programData->initProgramData(numIndices);
    630 }
    631 
    632 void GLSharedGroup::setShaderProgramIndexInfo(GLuint shaderProgram, GLuint index, GLint base, GLint size, GLenum type, const char* name) {
    633     ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    634     ProgramData* pData = spData->programData;
    635     ShaderData* sData = spData->shaderData;
    636 
    637     if (pData)
    638     {
    639         pData->setIndexInfo(index, base, size, type);
    640 
    641         if (type == GL_SAMPLER_2D) {
    642             ShaderData::StringList::iterator nameIter = sData->samplerExternalNames.begin();
    643             ShaderData::StringList::iterator nameEnd  = sData->samplerExternalNames.end();
    644             while (nameIter != nameEnd) {
    645                 if (*nameIter == name) {
    646                     pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
    647                     break;
    648                 }
    649                 ++nameIter;
    650             }
    651         }
    652     }
    653 }
    654 
    655 void GLSharedGroup::setupShaderProgramLocationShiftWAR(GLuint shaderProgram) {
    656     ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    657     spData->programData->setupLocationShiftWAR();
    658 }
    659