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 /**** BufferData ****/
     20 
     21 BufferData::BufferData() : m_size(0) {};
     22 BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
     23 {
     24     void * buffer = NULL;
     25     if (size>0) buffer = m_fixedBuffer.alloc(size);
     26     if (data) memcpy(buffer, data, size);
     27 }
     28 
     29 /**** ProgramData ****/
     30 ProgramData::ProgramData() : m_numIndexes(0),
     31                              m_initialized(false),
     32                              m_locShiftWAR(false)
     33 {
     34     m_Indexes = NULL;
     35 }
     36 
     37 void ProgramData::initProgramData(GLuint numIndexes)
     38 {
     39     m_initialized = true;
     40     m_numIndexes = numIndexes;
     41     delete[] m_Indexes;
     42     m_Indexes = new IndexInfo[numIndexes];
     43     m_locShiftWAR = false;
     44 }
     45 
     46 bool ProgramData::isInitialized()
     47 {
     48     return m_initialized;
     49 }
     50 
     51 ProgramData::~ProgramData()
     52 {
     53     delete[] m_Indexes;
     54     m_Indexes = NULL;
     55 }
     56 
     57 void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type)
     58 {
     59     if (index>=m_numIndexes)
     60         return;
     61     m_Indexes[index].base = base;
     62     m_Indexes[index].size = size;
     63     m_Indexes[index].type = type;
     64     if (index > 0) {
     65         m_Indexes[index].appBase = m_Indexes[index-1].appBase +
     66                                    m_Indexes[index-1].size;
     67     }
     68     else {
     69         m_Indexes[index].appBase = 0;
     70     }
     71     m_Indexes[index].hostLocsPerElement = 1;
     72     m_Indexes[index].flags = 0;
     73     m_Indexes[index].samplerValue = 0;
     74 }
     75 
     76 void ProgramData::setIndexFlags(GLuint index, GLuint flags)
     77 {
     78     if (index >= m_numIndexes)
     79         return;
     80     m_Indexes[index].flags |= flags;
     81 }
     82 
     83 GLuint ProgramData::getIndexForLocation(GLint location)
     84 {
     85     GLuint index = m_numIndexes;
     86     GLint minDist = -1;
     87     for (GLuint i=0;i<m_numIndexes;++i)
     88     {
     89         GLint dist = location - m_Indexes[i].base;
     90         if (dist >= 0 &&
     91             (minDist < 0 || dist < minDist)) {
     92             index = i;
     93             minDist = dist;
     94         }
     95     }
     96     return index;
     97 }
     98 
     99 GLenum ProgramData::getTypeForLocation(GLint location)
    100 {
    101     GLuint index = getIndexForLocation(location);
    102     if (index<m_numIndexes) {
    103         return m_Indexes[index].type;
    104     }
    105     return 0;
    106 }
    107 
    108 void ProgramData::setupLocationShiftWAR()
    109 {
    110     m_locShiftWAR = false;
    111     for (GLuint i=0; i<m_numIndexes; i++) {
    112         if (0 != (m_Indexes[i].base & 0xffff)) {
    113             return;
    114         }
    115     }
    116     // if we have one uniform at location 0, we do not need the WAR.
    117     if (m_numIndexes > 1) {
    118         m_locShiftWAR = true;
    119     }
    120 }
    121 
    122 GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex)
    123 {
    124     if (!m_locShiftWAR) return hostLoc;
    125 
    126     GLuint index = getIndexForLocation(hostLoc);
    127     if (index<m_numIndexes) {
    128         if (arrIndex > 0) {
    129             m_Indexes[index].hostLocsPerElement =
    130                               (hostLoc - m_Indexes[index].base) / arrIndex;
    131         }
    132         return m_Indexes[index].appBase + arrIndex;
    133     }
    134     return -1;
    135 }
    136 
    137 GLint ProgramData::locationWARAppToHost(GLint appLoc)
    138 {
    139     if (!m_locShiftWAR) return appLoc;
    140 
    141     for(GLuint i=0; i<m_numIndexes; i++) {
    142         GLint elemIndex = appLoc - m_Indexes[i].appBase;
    143         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
    144             return m_Indexes[i].base +
    145                    elemIndex * m_Indexes[i].hostLocsPerElement;
    146         }
    147     }
    148     return -1;
    149 }
    150 
    151 GLint ProgramData::getNextSamplerUniform(GLint index, GLint* val, GLenum* target)
    152 {
    153     for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {
    154         if (m_Indexes[i].type == GL_SAMPLER_2D) {
    155             if (val) *val = m_Indexes[i].samplerValue;
    156             if (target) {
    157                 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
    158                     *target = GL_TEXTURE_EXTERNAL_OES;
    159                 } else {
    160                     *target = GL_TEXTURE_2D;
    161                 }
    162             }
    163             return i;
    164         }
    165     }
    166     return -1;
    167 }
    168 
    169 bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target)
    170 {
    171     for (GLuint i = 0; i < m_numIndexes; i++) {
    172         GLint elemIndex = appLoc - m_Indexes[i].appBase;
    173         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
    174             if (m_Indexes[i].type == GL_TEXTURE_2D) {
    175                 m_Indexes[i].samplerValue = val;
    176                 if (target) {
    177                     if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
    178                         *target = GL_TEXTURE_EXTERNAL_OES;
    179                     } else {
    180                         *target = GL_TEXTURE_2D;
    181                     }
    182                 }
    183                 return true;
    184             }
    185         }
    186     }
    187     return false;
    188 }
    189 
    190 bool ProgramData::attachShader(GLuint shader)
    191 {
    192     size_t n = m_shaders.size();
    193     for (size_t i = 0; i < n; i++) {
    194         if (m_shaders[i] == shader) {
    195             return false;
    196         }
    197     }
    198     // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
    199     // due to the default parameters. This is the desired insertAt() overload.
    200     m_shaders.insertAt(shader, m_shaders.size(), 1);
    201     return true;
    202 }
    203 
    204 bool ProgramData::detachShader(GLuint shader)
    205 {
    206     size_t n = m_shaders.size();
    207     for (size_t i = 0; i < n; i++) {
    208         if (m_shaders[i] == shader) {
    209             m_shaders.removeAt(i);
    210             return true;
    211         }
    212     }
    213     return false;
    214 }
    215 
    216 /***** GLSharedGroup ****/
    217 
    218 GLSharedGroup::GLSharedGroup() :
    219     m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
    220     m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
    221     m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
    222 {
    223 }
    224 
    225 GLSharedGroup::~GLSharedGroup()
    226 {
    227     m_buffers.clear();
    228     m_programs.clear();
    229 }
    230 
    231 BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
    232 {
    233     android::AutoMutex _lock(m_lock);
    234     return m_buffers.valueFor(bufferId);
    235 }
    236 
    237 void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
    238 {
    239     android::AutoMutex _lock(m_lock);
    240     m_buffers.add(bufferId, new BufferData(size, data));
    241 }
    242 
    243 void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
    244 {
    245     android::AutoMutex _lock(m_lock);
    246     m_buffers.replaceValueFor(bufferId, new BufferData(size, data));
    247 }
    248 
    249 GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
    250 {
    251     android::AutoMutex _lock(m_lock);
    252     BufferData * buf = m_buffers.valueFor(bufferId);
    253     if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
    254 
    255     //it's safe to update now
    256     memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
    257     return GL_NO_ERROR;
    258 }
    259 
    260 void GLSharedGroup::deleteBufferData(GLuint bufferId)
    261 {
    262     android::AutoMutex _lock(m_lock);
    263     m_buffers.removeItem(bufferId);
    264 }
    265 
    266 void GLSharedGroup::addProgramData(GLuint program)
    267 {
    268     android::AutoMutex _lock(m_lock);
    269     ProgramData *pData = m_programs.valueFor(program);
    270     if (pData)
    271     {
    272         m_programs.removeItem(program);
    273         delete pData;
    274     }
    275 
    276     m_programs.add(program,new ProgramData());
    277 }
    278 
    279 void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
    280 {
    281     android::AutoMutex _lock(m_lock);
    282     ProgramData *pData = m_programs.valueFor(program);
    283     if (pData)
    284     {
    285         pData->initProgramData(numIndexes);
    286     }
    287 }
    288 
    289 bool GLSharedGroup::isProgramInitialized(GLuint program)
    290 {
    291     android::AutoMutex _lock(m_lock);
    292     ProgramData* pData = m_programs.valueFor(program);
    293     if (pData)
    294     {
    295         return pData->isInitialized();
    296     }
    297     return false;
    298 }
    299 
    300 void GLSharedGroup::deleteProgramData(GLuint program)
    301 {
    302     android::AutoMutex _lock(m_lock);
    303     ProgramData *pData = m_programs.valueFor(program);
    304     if (pData)
    305         delete pData;
    306     m_programs.removeItem(program);
    307 }
    308 
    309 void GLSharedGroup::attachShader(GLuint program, GLuint shader)
    310 {
    311     android::AutoMutex _lock(m_lock);
    312     ProgramData* programData = m_programs.valueFor(program);
    313     ssize_t idx = m_shaders.indexOfKey(shader);
    314     if (programData && idx >= 0) {
    315         if (programData->attachShader(shader)) {
    316             refShaderDataLocked(idx);
    317         }
    318     }
    319 }
    320 
    321 void GLSharedGroup::detachShader(GLuint program, GLuint shader)
    322 {
    323     android::AutoMutex _lock(m_lock);
    324     ProgramData* programData = m_programs.valueFor(program);
    325     ssize_t idx = m_shaders.indexOfKey(shader);
    326     if (programData && idx >= 0) {
    327         if (programData->detachShader(shader)) {
    328             unrefShaderDataLocked(idx);
    329         }
    330     }
    331 }
    332 
    333 void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
    334 {
    335     android::AutoMutex _lock(m_lock);
    336     ProgramData* pData = m_programs.valueFor(program);
    337     if (pData)
    338     {
    339         pData->setIndexInfo(index,base,size,type);
    340 
    341         if (type == GL_SAMPLER_2D) {
    342             size_t n = pData->getNumShaders();
    343             for (size_t i = 0; i < n; i++) {
    344                 GLuint shaderId = pData->getShader(i);
    345                 ShaderData* shader = m_shaders.valueFor(shaderId);
    346                 if (!shader) continue;
    347                 ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
    348                 ShaderData::StringList::iterator nameEnd  = shader->samplerExternalNames.end();
    349                 while (nameIter != nameEnd) {
    350                     if (*nameIter == name) {
    351                         pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
    352                         break;
    353                     }
    354                     ++nameIter;
    355                 }
    356             }
    357         }
    358     }
    359 }
    360 
    361 GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
    362 {
    363     android::AutoMutex _lock(m_lock);
    364     ProgramData* pData = m_programs.valueFor(program);
    365     GLenum type=0;
    366     if (pData)
    367     {
    368         type = pData->getTypeForLocation(location);
    369     }
    370     return type;
    371 }
    372 
    373 bool  GLSharedGroup::isProgram(GLuint program)
    374 {
    375     android::AutoMutex _lock(m_lock);
    376     ProgramData* pData = m_programs.valueFor(program);
    377     return (pData!=NULL);
    378 }
    379 
    380 void GLSharedGroup::setupLocationShiftWAR(GLuint program)
    381 {
    382     android::AutoMutex _lock(m_lock);
    383     ProgramData* pData = m_programs.valueFor(program);
    384     if (pData) pData->setupLocationShiftWAR();
    385 }
    386 
    387 GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
    388 {
    389     android::AutoMutex _lock(m_lock);
    390     ProgramData* pData = m_programs.valueFor(program);
    391     if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
    392     else return hostLoc;
    393 }
    394 
    395 GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
    396 {
    397     android::AutoMutex _lock(m_lock);
    398     ProgramData* pData = m_programs.valueFor(program);
    399     if (pData) return pData->locationWARAppToHost(appLoc);
    400     else return appLoc;
    401 }
    402 
    403 bool GLSharedGroup::needUniformLocationWAR(GLuint program)
    404 {
    405     android::AutoMutex _lock(m_lock);
    406     ProgramData* pData = m_programs.valueFor(program);
    407     if (pData) return pData->needUniformLocationWAR();
    408     return false;
    409 }
    410 
    411 GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
    412 {
    413     android::AutoMutex _lock(m_lock);
    414     ProgramData* pData = m_programs.valueFor(program);
    415     return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
    416 }
    417 
    418 bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
    419 {
    420     android::AutoMutex _lock(m_lock);
    421     ProgramData* pData = m_programs.valueFor(program);
    422     return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
    423 }
    424 
    425 bool GLSharedGroup::addShaderData(GLuint shader)
    426 {
    427     android::AutoMutex _lock(m_lock);
    428     ShaderData* data = new ShaderData;
    429     if (data) {
    430         if (m_shaders.add(shader, data) < 0) {
    431             delete data;
    432             data = NULL;
    433         }
    434         data->refcount = 1;
    435     }
    436     return data != NULL;
    437 }
    438 
    439 ShaderData* GLSharedGroup::getShaderData(GLuint shader)
    440 {
    441     android::AutoMutex _lock(m_lock);
    442     return m_shaders.valueFor(shader);
    443 }
    444 
    445 void GLSharedGroup::unrefShaderData(GLuint shader)
    446 {
    447     android::AutoMutex _lock(m_lock);
    448     ssize_t idx = m_shaders.indexOfKey(shader);
    449     if (idx >= 0) {
    450         unrefShaderDataLocked(idx);
    451     }
    452 }
    453 
    454 void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
    455 {
    456     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
    457     ShaderData* data = m_shaders.valueAt(shaderIdx);
    458     data->refcount++;
    459 }
    460 
    461 void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
    462 {
    463     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
    464     ShaderData* data = m_shaders.valueAt(shaderIdx);
    465     if (--data->refcount == 0) {
    466         delete data;
    467         m_shaders.removeItemsAt(shaderIdx);
    468     }
    469 }
    470