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