Home | History | Annotate | Download | only in GLcommon
      1 /*
      2 * Copyright 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 <GLcommon/GLEScontext.h>
     18 #include <GLcommon/GLconversion_macros.h>
     19 #include <GLcommon/GLESmacros.h>
     20 #include <GLES/gl.h>
     21 #include <GLES/glext.h>
     22 #include <GLcommon/GLESvalidate.h>
     23 #include <GLcommon/TextureUtils.h>
     24 #include <GLcommon/FramebufferData.h>
     25 #include <strings.h>
     26 #include <string.h>
     27 
     28 //decleration
     29 static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
     30 static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
     31 static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
     32 static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
     33 
     34 GLESConversionArrays::~GLESConversionArrays() {
     35     for(std::map<GLenum,ArrayData>::iterator it = m_arrays.begin(); it != m_arrays.end();it++) {
     36         if((*it).second.allocated){
     37             if((*it).second.type == GL_FLOAT){
     38                 GLfloat* p = (GLfloat *)((*it).second.data);
     39                 if(p) delete[] p;
     40             } else if((*it).second.type == GL_SHORT){
     41                 GLshort* p = (GLshort *)((*it).second.data);
     42                 if(p) delete[] p;
     43             }
     44         }
     45     }
     46 }
     47 
     48 void GLESConversionArrays::allocArr(unsigned int size,GLenum type){
     49     if(type == GL_FIXED){
     50         m_arrays[m_current].data = new GLfloat[size];
     51         m_arrays[m_current].type = GL_FLOAT;
     52     } else if(type == GL_BYTE){
     53         m_arrays[m_current].data = new GLshort[size];
     54         m_arrays[m_current].type = GL_SHORT;
     55     }
     56     m_arrays[m_current].stride = 0;
     57     m_arrays[m_current].allocated = true;
     58 }
     59 
     60 void GLESConversionArrays::setArr(void* data,unsigned int stride,GLenum type){
     61    m_arrays[m_current].type = type;
     62    m_arrays[m_current].data = data;
     63    m_arrays[m_current].stride = stride;
     64    m_arrays[m_current].allocated = false;
     65 }
     66 
     67 void* GLESConversionArrays::getCurrentData(){
     68     return m_arrays[m_current].data;
     69 }
     70 
     71 ArrayData& GLESConversionArrays::getCurrentArray(){
     72     return m_arrays[m_current];
     73 }
     74 
     75 unsigned int GLESConversionArrays::getCurrentIndex(){
     76     return m_current;
     77 }
     78 
     79 ArrayData& GLESConversionArrays::operator[](int i){
     80     return m_arrays[i];
     81 }
     82 
     83 void GLESConversionArrays::operator++(){
     84     m_current++;
     85 }
     86 
     87 GLDispatch     GLEScontext::s_glDispatch;
     88 emugl::Mutex   GLEScontext::s_lock;
     89 std::string*   GLEScontext::s_glExtensions= NULL;
     90 std::string    GLEScontext::s_glVendor;
     91 std::string    GLEScontext::s_glRenderer;
     92 std::string    GLEScontext::s_glVersion;
     93 GLSupport      GLEScontext::s_glSupport;
     94 
     95 Version::Version():m_major(0),
     96                    m_minor(0),
     97                    m_release(0){};
     98 
     99 Version::Version(int major,int minor,int release):m_major(major),
    100                                                   m_minor(minor),
    101                                                   m_release(release){};
    102 
    103 Version::Version(const Version& ver):m_major(ver.m_major),
    104                                      m_minor(ver.m_minor),
    105                                      m_release(ver.m_release){}
    106 
    107 Version::Version(const char* versionString){
    108     m_release = 0;
    109     if((!versionString) ||
    110       ((!(sscanf(versionString,"%d.%d"   ,&m_major,&m_minor) == 2)) &&
    111        (!(sscanf(versionString,"%d.%d.%d",&m_major,&m_minor,&m_release) == 3)))){
    112         m_major = m_minor = 0; // the version is not in the right format
    113     }
    114 }
    115 
    116 Version& Version::operator=(const Version& ver){
    117     m_major   = ver.m_major;
    118     m_minor   = ver.m_minor;
    119     m_release = ver.m_release;
    120     return *this;
    121 }
    122 
    123 bool Version::operator<(const Version& ver) const{
    124     if(m_major < ver.m_major) return true;
    125     if(m_major == ver.m_major){
    126         if(m_minor < ver.m_minor) return true;
    127         if(m_minor == ver.m_minor){
    128            return m_release < ver.m_release;
    129         }
    130     }
    131     return false;
    132 }
    133 
    134 void GLEScontext::init() {
    135 
    136     if (!s_glExtensions) {
    137         initCapsLocked(s_glDispatch.glGetString(GL_EXTENSIONS));
    138         s_glExtensions = new std::string("");
    139     }
    140 
    141     if (!m_initialized) {
    142         initExtensionString();
    143 
    144         int maxTexUnits = getMaxTexUnits();
    145         m_texState = new textureUnitState[maxTexUnits];
    146         for (int i=0;i<maxTexUnits;++i) {
    147             for (int j=0;j<NUM_TEXTURE_TARGETS;++j)
    148             {
    149                 m_texState[i][j].texture = 0;
    150                 m_texState[i][j].enabled = GL_FALSE;
    151             }
    152         }
    153     }
    154 }
    155 
    156 GLEScontext::GLEScontext():
    157                            m_initialized(false)    ,
    158                            m_activeTexture(0)      ,
    159                            m_unpackAlignment(4)    ,
    160                            m_glError(GL_NO_ERROR)  ,
    161                            m_texState(0)          ,
    162                            m_arrayBuffer(0)        ,
    163                            m_elementBuffer(0),
    164                            m_renderbuffer(0),
    165                            m_framebuffer(0)
    166 {
    167 };
    168 
    169 GLenum GLEScontext::getGLerror() {
    170     return m_glError;
    171 }
    172 
    173 void GLEScontext::setGLerror(GLenum err) {
    174     m_glError = err;
    175 }
    176 
    177 void GLEScontext::setActiveTexture(GLenum tex) {
    178    m_activeTexture = tex - GL_TEXTURE0;
    179 }
    180 
    181 GLEScontext::~GLEScontext() {
    182     for(ArraysMap::iterator it = m_map.begin(); it != m_map.end();it++) {
    183         GLESpointer* p = (*it).second;
    184         if(p) {
    185             delete p;
    186         }
    187     }
    188     delete[] m_texState;
    189     m_texState = NULL;
    190 }
    191 
    192 const GLvoid* GLEScontext::setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) {
    193     GLuint bufferName = m_arrayBuffer;
    194     if(bufferName) {
    195         unsigned int offset = SafeUIntFromPointer(data);
    196         GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    197         m_map[arrType]->setBuffer(size,type,stride,vbo,bufferName,offset,normalize);
    198         return  static_cast<const unsigned char*>(vbo->getData()) +  offset;
    199     }
    200     m_map[arrType]->setArray(size,type,stride,data,normalize);
    201     return data;
    202 }
    203 
    204 void GLEScontext::enableArr(GLenum arr,bool enable) {
    205     m_map[arr]->enable(enable);
    206 }
    207 
    208 bool GLEScontext::isArrEnabled(GLenum arr) {
    209     return m_map[arr]->isEnable();
    210 }
    211 
    212 const GLESpointer* GLEScontext::getPointer(GLenum arrType) {
    213     if (m_map.find(arrType) != m_map.end()) return m_map[arrType];
    214     return NULL;
    215 }
    216 
    217 static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
    218 
    219     for(unsigned int i = 0; i < nBytes;i+=strideOut) {
    220         const GLfixed* fixed_data = (const GLfixed *)dataIn;
    221         //filling attrib
    222         for(int j=0;j<attribSize;j++) {
    223             reinterpret_cast<GLfloat*>(&static_cast<unsigned char*>(dataOut)[i])[j] = X2F(fixed_data[j]);
    224         }
    225         dataIn += strideIn;
    226     }
    227 }
    228 
    229 static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
    230     for(int i = 0 ;i < count ;i++) {
    231         unsigned short index = indices_type == GL_UNSIGNED_BYTE? ((GLubyte *)indices)[i]:
    232                                                              ((GLushort *)indices)[i];
    233         const GLfixed* fixed_data = (GLfixed *)(dataIn  + index*strideIn);
    234         GLfloat* float_data = reinterpret_cast<GLfloat*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
    235 
    236         for(int j=0;j<attribSize;j++) {
    237             float_data[j] = X2F(fixed_data[j]);
    238          }
    239     }
    240 }
    241 
    242 static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
    243 
    244     for(unsigned int i = 0; i < nBytes;i+=strideOut) {
    245         const GLbyte* byte_data = (const GLbyte *)dataIn;
    246         //filling attrib
    247         for(int j=0;j<attribSize;j++) {
    248             reinterpret_cast<GLshort*>(&static_cast<unsigned char*>(dataOut)[i])[j] = B2S(byte_data[j]);
    249         }
    250         dataIn += strideIn;
    251     }
    252 }
    253 
    254 static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
    255     for(int i = 0 ;i < count ;i++) {
    256         unsigned short index = indices_type == GL_UNSIGNED_BYTE? ((GLubyte *)indices)[i]:
    257                                                              ((GLushort *)indices)[i];
    258         const GLbyte* bytes_data = (GLbyte *)(dataIn  + index*strideIn);
    259         GLshort* short_data = reinterpret_cast<GLshort*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
    260 
    261         for(int j=0;j<attribSize;j++) {
    262             short_data[j] = B2S(bytes_data[j]);
    263          }
    264     }
    265 }
    266 static void directToBytesRanges(GLint first,GLsizei count,GLESpointer* p,RangeList& list) {
    267 
    268     int attribSize = p->getSize()*4; //4 is the sizeof GLfixed or GLfloat in bytes
    269     int stride = p->getStride()?p->getStride():attribSize;
    270     int start  = p->getBufferOffset()+first*attribSize;
    271     if(!p->getStride()) {
    272         list.addRange(Range(start,count*attribSize));
    273     } else {
    274         for(int i = 0 ;i < count; i++,start+=stride) {
    275             list.addRange(Range(start,attribSize));
    276         }
    277     }
    278 }
    279 
    280 static void indirectToBytesRanges(const GLvoid* indices,GLenum indices_type,GLsizei count,GLESpointer* p,RangeList& list) {
    281 
    282     int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
    283     int stride = p->getStride()?p->getStride():attribSize;
    284     int start  = p->getBufferOffset();
    285     for(int i=0 ; i < count; i++) {
    286         GLushort index = (indices_type == GL_UNSIGNED_SHORT?
    287                          static_cast<const GLushort*>(indices)[i]:
    288                          static_cast<const GLubyte*>(indices)[i]);
    289         list.addRange(Range(start+index*stride,attribSize));
    290 
    291     }
    292 }
    293 
    294 int bytesRangesToIndices(RangeList& ranges,GLESpointer* p,GLushort* indices) {
    295 
    296     int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
    297     int stride = p->getStride()?p->getStride():attribSize;
    298     int offset = p->getBufferOffset();
    299 
    300     int n = 0;
    301     for(int i=0;i<ranges.size();i++) {
    302         int startIndex = (ranges[i].getStart() - offset) / stride;
    303         int nElements = ranges[i].getSize()/attribSize;
    304         for(int j=0;j<nElements;j++) {
    305             indices[n++] = startIndex+j;
    306         }
    307     }
    308     return n;
    309 }
    310 
    311 void GLEScontext::convertDirect(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
    312 
    313     GLenum type    = p->getType();
    314     int attribSize = p->getSize();
    315     unsigned int size = attribSize*count + first;
    316     unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
    317     cArrs.allocArr(size,type);
    318     int stride = p->getStride()?p->getStride():bytes*attribSize;
    319     const char* data = (const char*)p->getArrayData() + (first*stride);
    320 
    321     if(type == GL_FIXED) {
    322         convertFixedDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLfloat),attribSize*sizeof(GLfloat),attribSize);
    323     } else if(type == GL_BYTE) {
    324         convertByteDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLshort),attribSize*sizeof(GLshort),attribSize);
    325     }
    326 }
    327 
    328 void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
    329 
    330     RangeList ranges;
    331     RangeList conversions;
    332     GLushort* indices = NULL;
    333     int attribSize = p->getSize();
    334     int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
    335     char* data = (char*)p->getBufferData() + (first*stride);
    336 
    337     if(p->bufferNeedConversion()) {
    338         directToBytesRanges(first,count,p,ranges); //converting indices range to buffer bytes ranges by offset
    339         p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
    340 
    341         if(conversions.size()) { // there are some elements to convert
    342            indices = new GLushort[count];
    343            int nIndices = bytesRangesToIndices(conversions,p,indices); //converting bytes ranges by offset to indices in this array
    344            convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_SHORT,indices,stride,attribSize);
    345         }
    346     }
    347     if(indices) delete[] indices;
    348     cArrs.setArr(data,p->getStride(),GL_FLOAT);
    349 }
    350 
    351 int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
    352     //finding max index
    353     int max = 0;
    354     if(type == GL_UNSIGNED_BYTE) {
    355         GLubyte*  b_indices  =(GLubyte *)indices;
    356         for(int i=0;i<count;i++) {
    357             if(b_indices[i] > max) max = b_indices[i];
    358         }
    359     } else {
    360         GLushort* us_indices =(GLushort *)indices;
    361         for(int i=0;i<count;i++) {
    362             if(us_indices[i] > max) max = us_indices[i];
    363         }
    364     }
    365     return max;
    366 }
    367 
    368 void GLEScontext::convertIndirect(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
    369     GLenum type    = p->getType();
    370     int maxElements = findMaxIndex(count,type,indices) + 1;
    371 
    372     int attribSize = p->getSize();
    373     int size = attribSize * maxElements;
    374     unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
    375     cArrs.allocArr(size,type);
    376     int stride = p->getStride()?p->getStride():bytes*attribSize;
    377 
    378     const char* data = (const char*)p->getArrayData();
    379     if(type == GL_FIXED) {
    380         convertFixedIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLfloat),attribSize);
    381     } else if(type == GL_BYTE){
    382         convertByteIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLshort),attribSize);
    383     }
    384 }
    385 
    386 void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
    387     RangeList ranges;
    388     RangeList conversions;
    389     GLushort* conversionIndices = NULL;
    390     int attribSize = p->getSize();
    391     int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
    392     char* data = static_cast<char*>(p->getBufferData());
    393     if(p->bufferNeedConversion()) {
    394         indirectToBytesRanges(indices,indices_type,count,p,ranges); //converting indices range to buffer bytes ranges by offset
    395         p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
    396         if(conversions.size()) { // there are some elements to convert
    397             conversionIndices = new GLushort[count];
    398             int nIndices = bytesRangesToIndices(conversions,p,conversionIndices); //converting bytes ranges by offset to indices in this array
    399             convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_SHORT,conversionIndices,stride,attribSize);
    400         }
    401     }
    402     if(conversionIndices) delete[] conversionIndices;
    403     cArrs.setArr(data,p->getStride(),GL_FLOAT);
    404 }
    405 
    406 
    407 
    408 void GLEScontext::bindBuffer(GLenum target,GLuint buffer) {
    409     if(target == GL_ARRAY_BUFFER) {
    410         m_arrayBuffer = buffer;
    411     } else {
    412        m_elementBuffer = buffer;
    413     }
    414 }
    415 
    416 void GLEScontext::unbindBuffer(GLuint buffer) {
    417     if(m_arrayBuffer == buffer)
    418     {
    419         m_arrayBuffer = 0;
    420     }
    421     if(m_elementBuffer == buffer)
    422     {
    423         m_elementBuffer = 0;
    424     }
    425 }
    426 
    427 //checks if any buffer is binded to target
    428 bool GLEScontext::isBindedBuffer(GLenum target) {
    429     if(target == GL_ARRAY_BUFFER) {
    430         return m_arrayBuffer != 0;
    431     } else {
    432         return m_elementBuffer != 0;
    433     }
    434 }
    435 
    436 GLuint GLEScontext::getBuffer(GLenum target) {
    437     return target == GL_ARRAY_BUFFER ? m_arrayBuffer:m_elementBuffer;
    438 }
    439 
    440 GLvoid* GLEScontext::getBindedBuffer(GLenum target) {
    441     GLuint bufferName = getBuffer(target);
    442     if(!bufferName) return NULL;
    443 
    444     GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    445     return vbo->getData();
    446 }
    447 
    448 void GLEScontext::getBufferSize(GLenum target,GLint* param) {
    449     GLuint bufferName = getBuffer(target);
    450     GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    451     *param = vbo->getSize();
    452 }
    453 
    454 void GLEScontext::getBufferUsage(GLenum target,GLint* param) {
    455     GLuint bufferName = getBuffer(target);
    456     GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    457     *param = vbo->getUsage();
    458 }
    459 
    460 bool GLEScontext::setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage) {
    461     GLuint bufferName = getBuffer(target);
    462     if(!bufferName) return false;
    463     GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    464     return vbo->setBuffer(size,usage,data);
    465 }
    466 
    467 bool GLEScontext::setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data) {
    468 
    469     GLuint bufferName = getBuffer(target);
    470     if(!bufferName) return false;
    471     GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
    472     return vbo->setSubBuffer(offset,size,data);
    473 }
    474 
    475 const char * GLEScontext::getExtensionString() {
    476     const char * ret;
    477     s_lock.lock();
    478     if (s_glExtensions)
    479         ret = s_glExtensions->c_str();
    480     else
    481         ret="";
    482     s_lock.unlock();
    483     return ret;
    484 }
    485 
    486 const char * GLEScontext::getVendorString() const {
    487     return s_glVendor.c_str();
    488 }
    489 
    490 const char * GLEScontext::getRendererString() const {
    491     return s_glRenderer.c_str();
    492 }
    493 
    494 const char * GLEScontext::getVersionString() const {
    495     return s_glVersion.c_str();
    496 }
    497 
    498 void GLEScontext::getGlobalLock() {
    499     s_lock.lock();
    500 }
    501 
    502 void GLEScontext::releaseGlobalLock() {
    503     s_lock.unlock();
    504 }
    505 
    506 
    507 void GLEScontext::initCapsLocked(const GLubyte * extensionString)
    508 {
    509     const char* cstring = (const char*)extensionString;
    510 
    511     s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&s_glSupport.maxVertexAttribs);
    512     s_glDispatch.glGetIntegerv(GL_MAX_CLIP_PLANES,&s_glSupport.maxClipPlane);
    513     s_glDispatch.glGetIntegerv(GL_MAX_LIGHTS,&s_glSupport.maxLights);
    514     s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_glSupport.maxTexSize);
    515     s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_UNITS,&s_glSupport.maxTexUnits);
    516     s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&s_glSupport.maxTexImageUnits);
    517     const GLubyte* glslVersion = s_glDispatch.glGetString(GL_SHADING_LANGUAGE_VERSION);
    518     s_glSupport.glslVersion = Version((const  char*)(glslVersion));
    519 
    520     if (strstr(cstring,"GL_EXT_bgra ")!=NULL)
    521         s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888 = true;
    522 
    523     if (strstr(cstring,"GL_EXT_framebuffer_object ")!=NULL)
    524         s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT = true;
    525 
    526     if (strstr(cstring,"GL_ARB_vertex_blend ")!=NULL)
    527         s_glSupport.GL_ARB_VERTEX_BLEND = true;
    528 
    529     if (strstr(cstring,"GL_ARB_matrix_palette ")!=NULL)
    530         s_glSupport.GL_ARB_MATRIX_PALETTE = true;
    531 
    532     if (strstr(cstring,"GL_EXT_packed_depth_stencil ")!=NULL )
    533         s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL = true;
    534 
    535     if (strstr(cstring,"GL_OES_read_format ")!=NULL)
    536         s_glSupport.GL_OES_READ_FORMAT = true;
    537 
    538     if (strstr(cstring,"GL_ARB_half_float_pixel ")!=NULL)
    539         s_glSupport.GL_ARB_HALF_FLOAT_PIXEL = true;
    540 
    541     if (strstr(cstring,"GL_NV_half_float ")!=NULL)
    542         s_glSupport.GL_NV_HALF_FLOAT = true;
    543 
    544     if (strstr(cstring,"GL_ARB_half_float_vertex ")!=NULL)
    545         s_glSupport.GL_ARB_HALF_FLOAT_VERTEX = true;
    546 
    547     if (strstr(cstring,"GL_SGIS_generate_mipmap ")!=NULL)
    548         s_glSupport.GL_SGIS_GENERATE_MIPMAP = true;
    549 
    550     if (strstr(cstring,"GL_ARB_ES2_compatibility ")!=NULL)
    551         s_glSupport.GL_ARB_ES2_COMPATIBILITY = true;
    552 
    553     if (strstr(cstring,"GL_OES_standard_derivatives ")!=NULL)
    554         s_glSupport.GL_OES_STANDARD_DERIVATIVES = true;
    555 
    556 }
    557 
    558 void GLEScontext::buildStrings(const char* baseVendor,
    559         const char* baseRenderer, const char* baseVersion, const char* version)
    560 {
    561     static const char VENDOR[]   = {"Google ("};
    562     static const char RENDERER[] = {"Android Emulator OpenGL ES Translator ("};
    563     const size_t VENDOR_LEN   = sizeof(VENDOR) - 1;
    564     const size_t RENDERER_LEN = sizeof(RENDERER) - 1;
    565 
    566     size_t baseVendorLen = strlen(baseVendor);
    567     s_glVendor.clear();
    568     s_glVendor.reserve(baseVendorLen + VENDOR_LEN + 1);
    569     s_glVendor.append(VENDOR, VENDOR_LEN);
    570     s_glVendor.append(baseVendor, baseVendorLen);
    571     s_glVendor.append(")", 1);
    572 
    573     size_t baseRendererLen = strlen(baseRenderer);
    574     s_glRenderer.clear();
    575     s_glRenderer.reserve(baseRendererLen + RENDERER_LEN + 1);
    576     s_glRenderer.append(RENDERER, RENDERER_LEN);
    577     s_glRenderer.append(baseRenderer, baseRendererLen);
    578     s_glRenderer.append(")", 1);
    579 
    580     size_t baseVersionLen = strlen(baseVersion);
    581     size_t versionLen = strlen(version);
    582     s_glVersion.clear();
    583     s_glVersion.reserve(baseVersionLen + versionLen + 3);
    584     s_glVersion.append(version, versionLen);
    585     s_glVersion.append(" (", 2);
    586     s_glVersion.append(baseVersion, baseVersionLen);
    587     s_glVersion.append(")", 1);
    588 }
    589 
    590 bool GLEScontext::isTextureUnitEnabled(GLenum unit) {
    591     for (int i=0;i<NUM_TEXTURE_TARGETS;++i) {
    592         if (m_texState[unit-GL_TEXTURE0][i].enabled)
    593             return true;
    594     }
    595     return false;
    596 }
    597 
    598 bool GLEScontext::glGetBooleanv(GLenum pname, GLboolean *params)
    599 {
    600     GLint iParam;
    601 
    602     if(glGetIntegerv(pname, &iParam))
    603     {
    604         *params = (iParam != 0);
    605         return true;
    606     }
    607 
    608     return false;
    609 }
    610 
    611 bool GLEScontext::glGetFixedv(GLenum pname, GLfixed *params)
    612 {
    613     bool result = false;
    614     GLint numParams = 1;
    615 
    616     GLint* iParams = new GLint[numParams];
    617     if (numParams>0 && glGetIntegerv(pname,iParams)) {
    618         while(numParams >= 0)
    619         {
    620             params[numParams] = I2X(iParams[numParams]);
    621             numParams--;
    622         }
    623         result = true;
    624     }
    625     delete [] iParams;
    626 
    627     return result;
    628 }
    629 
    630 bool GLEScontext::glGetFloatv(GLenum pname, GLfloat *params)
    631 {
    632     bool result = false;
    633     GLint numParams = 1;
    634 
    635     GLint* iParams = new GLint[numParams];
    636     if (numParams>0 && glGetIntegerv(pname,iParams)) {
    637         while(numParams >= 0)
    638         {
    639             params[numParams] = (GLfloat)iParams[numParams];
    640             numParams--;
    641         }
    642         result = true;
    643     }
    644     delete [] iParams;
    645 
    646     return result;
    647 }
    648 
    649 bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params)
    650 {
    651     switch(pname)
    652     {
    653         case GL_ARRAY_BUFFER_BINDING:
    654             *params = m_arrayBuffer;
    655             break;
    656 
    657         case GL_ELEMENT_ARRAY_BUFFER_BINDING:
    658             *params = m_elementBuffer;
    659             break;
    660 
    661         case GL_TEXTURE_BINDING_CUBE_MAP:
    662             *params = m_texState[m_activeTexture][TEXTURE_CUBE_MAP].texture;
    663             break;
    664 
    665         case GL_TEXTURE_BINDING_2D:
    666             *params = m_texState[m_activeTexture][TEXTURE_2D].texture;
    667             break;
    668 
    669         case GL_ACTIVE_TEXTURE:
    670             *params = m_activeTexture+GL_TEXTURE0;
    671             break;
    672 
    673         case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
    674             *params = GL_UNSIGNED_BYTE;
    675             break;
    676 
    677         case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
    678             *params = GL_RGBA;
    679             break;
    680 
    681         case GL_MAX_TEXTURE_SIZE:
    682             *params = getMaxTexSize();
    683             break;
    684         default:
    685             return false;
    686     }
    687 
    688     return true;
    689 }
    690 
    691 TextureTarget GLEScontext::GLTextureTargetToLocal(GLenum target) {
    692     TextureTarget value=TEXTURE_2D;
    693     switch (target) {
    694     case GL_TEXTURE_CUBE_MAP:
    695     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    696     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    697     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    698     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    699     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    700     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    701         value = TEXTURE_CUBE_MAP;
    702         break;
    703     case GL_TEXTURE_2D:
    704         value = TEXTURE_2D;
    705         break;
    706     }
    707     return value;
    708 }
    709 
    710 unsigned int GLEScontext::getBindedTexture(GLenum target) {
    711     TextureTarget pos = GLTextureTargetToLocal(target);
    712     return m_texState[m_activeTexture][pos].texture;
    713 }
    714 
    715 unsigned int GLEScontext::getBindedTexture(GLenum unit, GLenum target) {
    716     TextureTarget pos = GLTextureTargetToLocal(target);
    717     return m_texState[unit-GL_TEXTURE0][pos].texture;
    718 }
    719 
    720 void GLEScontext::setBindedTexture(GLenum target, unsigned int tex) {
    721     TextureTarget pos = GLTextureTargetToLocal(target);
    722     m_texState[m_activeTexture][pos].texture = tex;
    723 }
    724 
    725 void GLEScontext::setTextureEnabled(GLenum target, GLenum enable) {
    726     TextureTarget pos = GLTextureTargetToLocal(target);
    727     m_texState[m_activeTexture][pos].enabled = enable;
    728 }
    729 
    730 #define INTERNAL_NAME(x) (x +0x100000000ll);
    731 
    732 ObjectLocalName GLEScontext::getDefaultTextureName(GLenum target) {
    733     ObjectLocalName name = 0;
    734     switch (GLTextureTargetToLocal(target)) {
    735     case TEXTURE_2D:
    736         name = INTERNAL_NAME(0);
    737         break;
    738     case TEXTURE_CUBE_MAP:
    739         name = INTERNAL_NAME(1);
    740         break;
    741     default:
    742         name = 0;
    743         break;
    744     }
    745     return name;
    746 }
    747 
    748 void GLEScontext::drawValidate(void)
    749 {
    750     if(m_framebuffer == 0)
    751         return;
    752 
    753     ObjectDataPtr fbObj = m_shareGroup->getObjectData(FRAMEBUFFER,m_framebuffer);
    754     if (fbObj.Ptr() == NULL)
    755         return;
    756 
    757     FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
    758 
    759     fbData->validate(this);
    760 }
    761