Home | History | Annotate | Download | only in GLESv1_enc
      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 #include "GLEncoder.h"
     17 #include "glUtils.h"
     18 #include "FixedBuffer.h"
     19 #include <private/ui/android_natives_priv.h>
     20 #include <cutils/log.h>
     21 #include <assert.h>
     22 
     23 #ifndef MIN
     24 #define MIN(a, b) ((a) < (b) ? (a) : (b))
     25 #endif
     26 
     27 static GLubyte *gVendorString= (GLubyte *) "Android";
     28 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 1.0";
     29 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0";
     30 static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
     31 
     32 #define SET_ERROR_IF(condition,err) if((condition)) {                            \
     33         LOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     34         ctx->setError(err);                                    \
     35         return;                                                  \
     36     }
     37 
     38 
     39 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
     40         LOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     41         ctx->setError(err);                                    \
     42         return ret;                                              \
     43     }
     44 
     45 GLenum GLEncoder::s_glGetError(void * self)
     46 {
     47     GLEncoder *ctx = (GLEncoder *)self;
     48     GLenum err = ctx->getError();
     49     if(err != GL_NO_ERROR) {
     50         ctx->setError(GL_NO_ERROR);
     51         return err;
     52     }
     53 
     54     return ctx->m_glGetError_enc(self);
     55 
     56 }
     57 
     58 GLint * GLEncoder::getCompressedTextureFormats()
     59 {
     60     if (m_compressedTextureFormats == NULL) {
     61         this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
     62                             &m_num_compressedTextureFormats);
     63         if (m_num_compressedTextureFormats > 0) {
     64             // get number of texture formats;
     65             m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
     66             this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
     67         }
     68     }
     69     return m_compressedTextureFormats;
     70 }
     71 
     72 void GLEncoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
     73 {
     74     GLEncoder *ctx = (GLEncoder *)self;
     75     assert(ctx->m_state != NULL);
     76     GLClientState* state = ctx->m_state;
     77 
     78     switch (param) {
     79     case GL_COMPRESSED_TEXTURE_FORMATS: {
     80         GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
     81         if (ctx->m_num_compressedTextureFormats > 0 &&
     82                 compressedTextureFormats != NULL) {
     83             memcpy(ptr, compressedTextureFormats,
     84                    ctx->m_num_compressedTextureFormats * sizeof(GLint));
     85         }
     86         break;
     87     }
     88 
     89     case GL_MAX_TEXTURE_UNITS:
     90         ctx->m_glGetIntegerv_enc(self, param, ptr);
     91         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
     92         break;
     93 
     94     case GL_TEXTURE_BINDING_2D:
     95         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
     96         break;
     97 
     98     case GL_TEXTURE_BINDING_EXTERNAL_OES:
     99         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    100         break;
    101 
    102     default:
    103         if (!state->getClientStateParameter<GLint>(param,ptr)) {
    104             ctx->m_glGetIntegerv_enc(self, param, ptr);
    105         }
    106         break;
    107     }
    108 }
    109 
    110 void GLEncoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
    111 {
    112     GLEncoder *ctx = (GLEncoder *)self;
    113     assert(ctx->m_state != NULL);
    114     GLClientState* state = ctx->m_state;
    115 
    116     switch (param) {
    117     case GL_COMPRESSED_TEXTURE_FORMATS: {
    118         GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
    119         if (ctx->m_num_compressedTextureFormats > 0 &&
    120                 compressedTextureFormats != NULL) {
    121             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    122                 ptr[i] = (GLfloat) compressedTextureFormats[i];
    123             }
    124         }
    125         break;
    126     }
    127 
    128     case GL_MAX_TEXTURE_UNITS:
    129         ctx->m_glGetFloatv_enc(self, param, ptr);
    130         *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
    131         break;
    132 
    133     case GL_TEXTURE_BINDING_2D:
    134         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
    135         break;
    136 
    137     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    138         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    139         break;
    140 
    141     default:
    142         if (!state->getClientStateParameter<GLfloat>(param,ptr)) {
    143             ctx->m_glGetFloatv_enc(self, param, ptr);
    144         }
    145         break;
    146     }
    147 }
    148 
    149 void GLEncoder::s_glGetFixedv(void *self, GLenum param, GLfixed *ptr)
    150 {
    151     GLEncoder *ctx = (GLEncoder *)self;
    152     assert(ctx->m_state != NULL);
    153     GLClientState* state = ctx->m_state;
    154 
    155     switch (param) {
    156     case GL_COMPRESSED_TEXTURE_FORMATS: {
    157         GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
    158         if (ctx->m_num_compressedTextureFormats > 0 &&
    159                 compressedTextureFormats != NULL) {
    160             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    161                 ptr[i] =  compressedTextureFormats[i] << 16;
    162             }
    163         }
    164         break;
    165     }
    166 
    167     case GL_MAX_TEXTURE_UNITS:
    168         ctx->m_glGetFixedv_enc(self, param, ptr);
    169         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS << 16);
    170         break;
    171 
    172     case GL_TEXTURE_BINDING_2D:
    173         *ptr = state->getBoundTexture(GL_TEXTURE_2D) << 16;
    174         break;
    175 
    176     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    177         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) << 16;
    178         break;
    179 
    180     default:
    181         if (!state->getClientStateParameter<GLfixed>(param,ptr)) {
    182             ctx->m_glGetFixedv_enc(self, param, ptr);
    183         }
    184         break;
    185     }
    186 }
    187 
    188 void GLEncoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
    189 {
    190     GLEncoder *ctx = (GLEncoder *)self;
    191     assert(ctx->m_state != NULL);
    192     GLClientState* state = ctx->m_state;
    193 
    194     switch (param) {
    195     case GL_COMPRESSED_TEXTURE_FORMATS: {
    196         GLint* compressedTextureFormats = ctx->getCompressedTextureFormats();
    197         if (ctx->m_num_compressedTextureFormats > 0 &&
    198                 compressedTextureFormats != NULL) {
    199             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    200                 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
    201             }
    202         }
    203         break;
    204     }
    205 
    206     case GL_TEXTURE_BINDING_2D:
    207         *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
    208         break;
    209 
    210     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    211         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
    212                 ? GL_TRUE : GL_FALSE;
    213         break;
    214 
    215     default:
    216         if (!state->getClientStateParameter<GLboolean>(param,ptr)) {
    217             ctx->m_glGetBooleanv_enc(self, param, ptr);
    218         }
    219         break;
    220     }
    221 }
    222 
    223 void GLEncoder::s_glGetPointerv(void * self, GLenum param, GLvoid **params)
    224 {
    225     GLEncoder * ctx = (GLEncoder *) self;
    226     assert(ctx->m_state != NULL);
    227     ctx->m_state->getClientStatePointer(param,params);
    228 }
    229 
    230 void GLEncoder::s_glFlush(void *self)
    231 {
    232     GLEncoder *ctx = (GLEncoder *)self;
    233     ctx->m_glFlush_enc(self);
    234     ctx->m_stream->flush();
    235 }
    236 
    237 const GLubyte *GLEncoder::s_glGetString(void *self, GLenum name)
    238 {
    239     GLubyte *retval =  (GLubyte *) "";
    240     switch(name) {
    241     case GL_VENDOR:
    242         retval = gVendorString;
    243         break;
    244     case GL_RENDERER:
    245         retval = gRendererString;
    246         break;
    247     case GL_VERSION:
    248         retval = gVersionString;
    249         break;
    250     case GL_EXTENSIONS:
    251         retval = gExtensionsString;
    252         break;
    253     }
    254     return retval;
    255 }
    256 
    257 void GLEncoder::s_glPixelStorei(void *self, GLenum param, GLint value)
    258 {
    259     GLEncoder *ctx = (GLEncoder *)self;
    260     ctx->m_glPixelStorei_enc(ctx, param, value);
    261     LOG_ASSERT(ctx->m_state, "GLEncoder::s_glPixelStorei");
    262     ctx->m_state->setPixelStore(param, value);
    263 }
    264 
    265 void GLEncoder::s_glVertexPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
    266 {
    267     GLEncoder *ctx = (GLEncoder *)self;
    268     assert(ctx->m_state != NULL);
    269     ctx->m_state->setState(GLClientState::VERTEX_LOCATION, size, type, false, stride, data);
    270 }
    271 
    272 void GLEncoder::s_glNormalPointer(void *self, GLenum type, GLsizei stride, const void *data)
    273 {
    274     GLEncoder *ctx = (GLEncoder *)self;
    275     assert(ctx->m_state != NULL);
    276     ctx->m_state->setState(GLClientState::NORMAL_LOCATION, 3, type, false, stride, data);
    277 }
    278 
    279 void GLEncoder::s_glColorPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
    280 {
    281     GLEncoder *ctx = (GLEncoder *)self;
    282     assert(ctx->m_state != NULL);
    283     ctx->m_state->setState(GLClientState::COLOR_LOCATION, size, type, false, stride, data);
    284 }
    285 
    286 void GLEncoder::s_glPointsizePointer(void *self, GLenum type, GLsizei stride, const void *data)
    287 {
    288     GLEncoder *ctx = (GLEncoder *)self;
    289     assert(ctx->m_state != NULL);
    290     ctx->m_state->setState(GLClientState::POINTSIZE_LOCATION, 1, type, false, stride, data);
    291 }
    292 
    293 void GLEncoder::s_glClientActiveTexture(void *self, GLenum texture)
    294 {
    295     GLEncoder *ctx = (GLEncoder *)self;
    296     assert(ctx->m_state != NULL);
    297     ctx->m_state->setActiveTexture(texture - GL_TEXTURE0);
    298 }
    299 
    300 void GLEncoder::s_glTexcoordPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
    301 {
    302     GLEncoder *ctx = (GLEncoder *)self;
    303     assert(ctx->m_state != NULL);
    304     int loc = ctx->m_state->getLocation(GL_TEXTURE_COORD_ARRAY);
    305     ctx->m_state->setState(loc, size, type, false, stride, data);
    306 }
    307 
    308 void GLEncoder::s_glMatrixIndexPointerOES(void *self, int size, GLenum type, GLsizei stride, const void * data)
    309 {
    310     GLEncoder *ctx = (GLEncoder *)self;
    311     assert(ctx->m_state != NULL);
    312     int loc = ctx->m_state->getLocation(GL_MATRIX_INDEX_ARRAY_OES);
    313     ctx->m_state->setState(loc, size, type, false, stride, data);
    314 }
    315 
    316 void GLEncoder::s_glWeightPointerOES(void * self, int size, GLenum type, GLsizei stride, const void * data)
    317 {
    318     GLEncoder *ctx = (GLEncoder *)self;
    319     assert(ctx->m_state != NULL);
    320     int loc = ctx->m_state->getLocation(GL_WEIGHT_ARRAY_OES);
    321     ctx->m_state->setState(loc, size, type, false, stride, data);
    322 }
    323 
    324 void GLEncoder::s_glEnableClientState(void *self, GLenum state)
    325 {
    326     GLEncoder *ctx = (GLEncoder *) self;
    327     assert(ctx->m_state != NULL);
    328     int loc = ctx->m_state->getLocation(state);
    329     ctx->m_state->enable(loc, 1);
    330 }
    331 
    332 void GLEncoder::s_glDisableClientState(void *self, GLenum state)
    333 {
    334     GLEncoder *ctx = (GLEncoder *) self;
    335     assert(ctx->m_state != NULL);
    336     int loc = ctx->m_state->getLocation(state);
    337     ctx->m_state->enable(loc, 0);
    338 }
    339 
    340 GLboolean GLEncoder::s_glIsEnabled(void *self, GLenum cap)
    341 {
    342     GLEncoder *ctx = (GLEncoder *) self;
    343     assert(ctx->m_state != NULL);
    344     int loc = ctx->m_state->getLocation(cap);
    345     const GLClientState::VertexAttribState *state = ctx->m_state->getState(loc);
    346 
    347     if (state!=NULL)
    348       return state->enabled;
    349 
    350     return ctx->m_glIsEnabled_enc(self,cap);
    351 }
    352 
    353 void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
    354 {
    355     GLEncoder *ctx = (GLEncoder *) self;
    356     assert(ctx->m_state != NULL);
    357     ctx->m_state->bindBuffer(target, id);
    358     // TODO set error state if needed;
    359     ctx->m_glBindBuffer_enc(self, target, id);
    360 }
    361 
    362 void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
    363 {
    364     GLEncoder *ctx = (GLEncoder *) self;
    365     GLuint bufferId = ctx->m_state->getBuffer(target);
    366     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    367     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
    368 
    369     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
    370     ctx->m_glBufferData_enc(self, target, size, data, usage);
    371 }
    372 
    373 void GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
    374 {
    375     GLEncoder *ctx = (GLEncoder *) self;
    376     GLuint bufferId = ctx->m_state->getBuffer(target);
    377     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    378 
    379     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
    380     SET_ERROR_IF(res, res);
    381 
    382     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
    383 }
    384 
    385 void GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
    386 {
    387     GLEncoder *ctx = (GLEncoder *) self;
    388     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
    389     for (int i=0; i<n; i++) {
    390         ctx->m_shared->deleteBufferData(buffers[i]);
    391         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
    392     }
    393 }
    394 
    395 void GLEncoder::sendVertexData(unsigned int first, unsigned int count)
    396 {
    397     assert(m_state != NULL);
    398     for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
    399         bool enableDirty;
    400         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
    401 
    402         // do not process if state not valid
    403         if (!state) continue;
    404 
    405         // do not send disable state if state was already disabled
    406         if (!enableDirty && !state->enabled) continue;
    407 
    408         if ( i >= GLClientState::TEXCOORD0_LOCATION &&
    409             i <= GLClientState::TEXCOORD7_LOCATION ) {
    410             m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION);
    411         }
    412 
    413         if (state->enabled) {
    414 
    415             if (enableDirty)
    416                 m_glEnableClientState_enc(this, state->glConst);
    417 
    418             unsigned int datalen = state->elementSize * count;
    419             int stride = state->stride;
    420             if (stride == 0) stride = state->elementSize;
    421             int firstIndex = stride * first;
    422 
    423             if (state->bufferObject == 0) {
    424 
    425                 switch(i) {
    426                 case GLClientState::VERTEX_LOCATION:
    427                     this->glVertexPointerData(this, state->size, state->type, state->stride,
    428                                               (unsigned char *)state->data + firstIndex, datalen);
    429                     break;
    430                 case GLClientState::NORMAL_LOCATION:
    431                     this->glNormalPointerData(this, state->type, state->stride,
    432                                               (unsigned char *)state->data + firstIndex, datalen);
    433                     break;
    434                 case GLClientState::COLOR_LOCATION:
    435                     this->glColorPointerData(this, state->size, state->type, state->stride,
    436                                              (unsigned char *)state->data + firstIndex, datalen);
    437                     break;
    438                 case GLClientState::TEXCOORD0_LOCATION:
    439                 case GLClientState::TEXCOORD1_LOCATION:
    440                 case GLClientState::TEXCOORD2_LOCATION:
    441                 case GLClientState::TEXCOORD3_LOCATION:
    442                 case GLClientState::TEXCOORD4_LOCATION:
    443                 case GLClientState::TEXCOORD5_LOCATION:
    444                 case GLClientState::TEXCOORD6_LOCATION:
    445                 case GLClientState::TEXCOORD7_LOCATION:
    446                     this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state->size, state->type, state->stride,
    447                                                 (unsigned char *)state->data + firstIndex, datalen);
    448                     break;
    449                 case GLClientState::POINTSIZE_LOCATION:
    450                     this->glPointSizePointerData(this, state->type, state->stride,
    451                                                  (unsigned char *) state->data + firstIndex, datalen);
    452                     break;
    453                 case GLClientState::WEIGHT_LOCATION:
    454                     this->glWeightPointerData(this, state->size, state->type, state->stride,
    455                                               (unsigned char * ) state->data + firstIndex, datalen);
    456                     break;
    457                 case GLClientState::MATRIXINDEX_LOCATION:
    458                     this->glMatrixIndexPointerData(this, state->size, state->type, state->stride,
    459                                                   (unsigned char *)state->data + firstIndex, datalen);
    460                     break;
    461                 }
    462             } else {
    463                 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
    464 
    465                 switch(i) {
    466                 case GLClientState::VERTEX_LOCATION:
    467                     this->glVertexPointerOffset(this, state->size, state->type, state->stride,
    468                                                 (GLuint)state->data + firstIndex);
    469                     break;
    470                 case GLClientState::NORMAL_LOCATION:
    471                     this->glNormalPointerOffset(this, state->type, state->stride,
    472                                                 (GLuint) state->data + firstIndex);
    473                     break;
    474                 case GLClientState::POINTSIZE_LOCATION:
    475                     this->glPointSizePointerOffset(this, state->type, state->stride,
    476                                                    (GLuint) state->data + firstIndex);
    477                     break;
    478                 case GLClientState::COLOR_LOCATION:
    479                     this->glColorPointerOffset(this, state->size, state->type, state->stride,
    480                                                (GLuint) state->data + firstIndex);
    481                     break;
    482                 case GLClientState::TEXCOORD0_LOCATION:
    483                 case GLClientState::TEXCOORD1_LOCATION:
    484                 case GLClientState::TEXCOORD2_LOCATION:
    485                 case GLClientState::TEXCOORD3_LOCATION:
    486                 case GLClientState::TEXCOORD4_LOCATION:
    487                 case GLClientState::TEXCOORD5_LOCATION:
    488                 case GLClientState::TEXCOORD6_LOCATION:
    489                 case GLClientState::TEXCOORD7_LOCATION:
    490                     this->glTexCoordPointerOffset(this, state->size, state->type, state->stride,
    491                                                   (GLuint) state->data + firstIndex);
    492                     break;
    493                 case GLClientState::WEIGHT_LOCATION:
    494                     this->glWeightPointerOffset(this,state->size,state->type,state->stride,
    495                                                 (GLuint)state->data+firstIndex);
    496                     break;
    497                 case GLClientState::MATRIXINDEX_LOCATION:
    498                     this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride,
    499                                               (GLuint)state->data+firstIndex);
    500                     break;
    501                 }
    502                 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
    503             }
    504         } else {
    505             this->m_glDisableClientState_enc(this, state->glConst);
    506         }
    507     }
    508 }
    509 
    510 void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
    511 {
    512     GLEncoder *ctx = (GLEncoder *)self;
    513 
    514     ctx->sendVertexData(first, count);
    515     ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count);
    516 }
    517 
    518 void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
    519 {
    520 
    521     GLEncoder *ctx = (GLEncoder *)self;
    522     assert(ctx->m_state != NULL);
    523     SET_ERROR_IF(count<0, GL_INVALID_VALUE);
    524 
    525     bool has_immediate_arrays = false;
    526     bool has_indirect_arrays = false;
    527 
    528     for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
    529         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
    530         if (state->enabled) {
    531             if (state->bufferObject != 0) {
    532                 has_indirect_arrays = true;
    533             } else {
    534                 has_immediate_arrays = true;
    535             }
    536         }
    537     }
    538 
    539     if (!has_immediate_arrays && !has_indirect_arrays) {
    540         LOGE("glDrawElements: no data bound to the command - ignoring\n");
    541         return;
    542     }
    543 
    544     bool adjustIndices = true;
    545     if (ctx->m_state->currentIndexVbo() != 0) {
    546         if (!has_immediate_arrays) {
    547             ctx->sendVertexData(0, count);
    548             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
    549             ctx->glDrawElementsOffset(ctx, mode, count, type, (GLuint)indices);
    550             adjustIndices = false;
    551         } else {
    552             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
    553             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
    554             indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
    555         }
    556     }
    557     if (adjustIndices) {
    558         void *adjustedIndices = (void*)indices;
    559         int minIndex = 0, maxIndex = 0;
    560 
    561         switch(type) {
    562         case GL_BYTE:
    563         case GL_UNSIGNED_BYTE:
    564             GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
    565             if (minIndex != 0) {
    566                 adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
    567                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
    568                                                  (unsigned char *)adjustedIndices,
    569                                                  count, -minIndex);
    570             }
    571             break;
    572         case GL_SHORT:
    573         case GL_UNSIGNED_SHORT:
    574             GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
    575             if (minIndex != 0) {
    576                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
    577                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
    578                                                  (unsigned short *)adjustedIndices,
    579                                                  count, -minIndex);
    580             }
    581             break;
    582         default:
    583             LOGE("unsupported index buffer type %d\n", type);
    584         }
    585         if (has_indirect_arrays || 1) {
    586             ctx->sendVertexData(minIndex, maxIndex - minIndex + 1);
    587             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
    588                                       count * glSizeof(type));
    589             // XXX - OPTIMIZATION (see the other else branch) should be implemented
    590             if(!has_indirect_arrays) {
    591                 //LOGD("unoptimized drawelements !!!\n");
    592             }
    593         } else {
    594             // we are all direct arrays and immidate mode index array -
    595             // rebuild the arrays and the index array;
    596             LOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
    597         }
    598     }
    599 }
    600 
    601 void GLEncoder::s_glActiveTexture(void* self, GLenum texture)
    602 {
    603     GLEncoder* ctx = (GLEncoder*)self;
    604     GLClientState* state = ctx->m_state;
    605     GLenum err;
    606 
    607     if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) {
    608         LOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
    609         ctx->setError(err);
    610         return;
    611     }
    612 
    613     ctx->m_glActiveTexture_enc(ctx, texture);
    614 }
    615 
    616 void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
    617 {
    618     GLEncoder* ctx = (GLEncoder*)self;
    619     GLClientState* state = ctx->m_state;
    620     GLenum err;
    621 
    622     GLboolean firstUse;
    623     if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) {
    624         LOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
    625         ctx->setError(err);
    626         return;
    627     }
    628 
    629     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
    630         ctx->m_glBindTexture_enc(ctx, target, texture);
    631         return;
    632     }
    633 
    634     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
    635 
    636     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
    637         // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D
    638         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
    639         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
    640                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    641         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
    642                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    643         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
    644                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    645 
    646         if (target != priorityTarget) {
    647             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
    648                     state->getBoundTexture(GL_TEXTURE_2D));
    649         }
    650     }
    651 
    652     if (target == priorityTarget) {
    653         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
    654     }
    655 }
    656 
    657 void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
    658 {
    659     GLEncoder* ctx = (GLEncoder*)self;
    660     GLClientState* state = ctx->m_state;
    661 
    662     state->deleteTextures(n, textures);
    663     ctx->m_glDeleteTextures_enc(ctx, n, textures);
    664 }
    665 
    666 void GLEncoder::s_glDisable(void* self, GLenum cap)
    667 {
    668     GLEncoder* ctx = (GLEncoder*)self;
    669     GLClientState* state = ctx->m_state;
    670 
    671     if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
    672         GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
    673         state->disableTextureTarget(cap);
    674         GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
    675 
    676         if (prevTarget != currTarget) {
    677             if (currTarget == GL_INVALID_ENUM) {
    678                 ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D);
    679                 currTarget = GL_TEXTURE_2D;
    680             }
    681             // maintain the invariant that when TEXTURE_EXTERNAL_OES is
    682             // disabled, the TEXTURE_2D binding is active, even if
    683             // TEXTURE_2D is also disabled.
    684             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
    685                     state->getBoundTexture(currTarget));
    686         }
    687 
    688     } else {
    689         ctx->m_glDisable_enc(ctx, cap);
    690     }
    691 }
    692 
    693 void GLEncoder::s_glEnable(void* self, GLenum cap)
    694 {
    695     GLEncoder* ctx = (GLEncoder*)self;
    696     GLClientState* state = ctx->m_state;
    697 
    698     if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
    699         GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
    700         state->enableTextureTarget(cap);
    701         GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
    702 
    703         if (prevTarget != currTarget) {
    704             if (prevTarget == GL_INVALID_ENUM) {
    705                 ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D);
    706             }
    707             if (currTarget == GL_TEXTURE_EXTERNAL_OES) {
    708                 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
    709                         state->getBoundTexture(currTarget));
    710             }
    711         }
    712 
    713     } else {
    714         ctx->m_glEnable_enc(ctx, cap);
    715     }
    716 }
    717 
    718 void GLEncoder::s_glGetTexParameterfv(void* self,
    719         GLenum target, GLenum pname, GLfloat* params)
    720 {
    721     GLEncoder* ctx = (GLEncoder*)self;
    722     const GLClientState* state = ctx->m_state;
    723 
    724     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    725         ctx->override2DTextureTarget(target);
    726         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
    727         ctx->restore2DTextureTarget();
    728     } else {
    729         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
    730     }
    731 }
    732 
    733 void GLEncoder::s_glGetTexParameteriv(void* self,
    734         GLenum target, GLenum pname, GLint* params)
    735 {
    736     GLEncoder* ctx = (GLEncoder*)self;
    737     const GLClientState* state = ctx->m_state;
    738 
    739     switch (pname) {
    740     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
    741         *params = 1;
    742         break;
    743 
    744     default:
    745         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    746             ctx->override2DTextureTarget(target);
    747             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
    748             ctx->restore2DTextureTarget();
    749         } else {
    750             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
    751         }
    752         break;
    753     }
    754 }
    755 
    756 void GLEncoder::s_glGetTexParameterxv(void* self,
    757         GLenum target, GLenum pname, GLfixed* params)
    758 {
    759     GLEncoder* ctx = (GLEncoder*)self;
    760     const GLClientState* state = ctx->m_state;
    761 
    762     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    763         ctx->override2DTextureTarget(target);
    764         ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
    765         ctx->restore2DTextureTarget();
    766     } else {
    767         ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params);
    768     }
    769 }
    770 
    771 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
    772 {
    773     switch (pname) {
    774     case GL_TEXTURE_MIN_FILTER:
    775     case GL_TEXTURE_MAG_FILTER:
    776         return param == GL_NEAREST || param == GL_LINEAR;
    777 
    778     case GL_TEXTURE_WRAP_S:
    779     case GL_TEXTURE_WRAP_T:
    780         return param == GL_CLAMP_TO_EDGE;
    781 
    782     case GL_GENERATE_MIPMAP:
    783         return param == GL_FALSE;
    784 
    785     default:
    786         return true;
    787     }
    788 }
    789 
    790 void GLEncoder::s_glTexParameterf(void* self,
    791         GLenum target, GLenum pname, GLfloat param)
    792 {
    793     GLEncoder* ctx = (GLEncoder*)self;
    794     const GLClientState* state = ctx->m_state;
    795 
    796     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    797             !isValidTextureExternalParam(pname, (GLenum)param)),
    798             GL_INVALID_ENUM);
    799 
    800     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    801         ctx->override2DTextureTarget(target);
    802         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
    803         ctx->restore2DTextureTarget();
    804     } else {
    805         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
    806     }
    807 }
    808 
    809 void GLEncoder::s_glTexParameterfv(void* self,
    810         GLenum target, GLenum pname, const GLfloat* params)
    811 {
    812     GLEncoder* ctx = (GLEncoder*)self;
    813     const GLClientState* state = ctx->m_state;
    814 
    815     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    816             !isValidTextureExternalParam(pname, (GLenum)params[0])),
    817             GL_INVALID_ENUM);
    818 
    819     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    820         ctx->override2DTextureTarget(target);
    821         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
    822         ctx->restore2DTextureTarget();
    823     } else {
    824         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
    825     }
    826 }
    827 
    828 void GLEncoder::s_glTexParameteri(void* self,
    829         GLenum target, GLenum pname, GLint param)
    830 {
    831     GLEncoder* ctx = (GLEncoder*)self;
    832     const GLClientState* state = ctx->m_state;
    833 
    834     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    835             !isValidTextureExternalParam(pname, (GLenum)param)),
    836             GL_INVALID_ENUM);
    837 
    838     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    839         ctx->override2DTextureTarget(target);
    840         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
    841         ctx->restore2DTextureTarget();
    842     } else {
    843         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
    844     }
    845 }
    846 
    847 void GLEncoder::s_glTexParameterx(void* self,
    848         GLenum target, GLenum pname, GLfixed param)
    849 {
    850     GLEncoder* ctx = (GLEncoder*)self;
    851     const GLClientState* state = ctx->m_state;
    852 
    853     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    854             !isValidTextureExternalParam(pname, (GLenum)param)),
    855             GL_INVALID_ENUM);
    856 
    857     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    858         ctx->override2DTextureTarget(target);
    859         ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param);
    860         ctx->restore2DTextureTarget();
    861     } else {
    862         ctx->m_glTexParameterx_enc(ctx, target, pname, param);
    863     }
    864 }
    865 
    866 void GLEncoder::s_glTexParameteriv(void* self,
    867         GLenum target, GLenum pname, const GLint* params)
    868 {
    869     GLEncoder* ctx = (GLEncoder*)self;
    870     const GLClientState* state = ctx->m_state;
    871 
    872     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    873             !isValidTextureExternalParam(pname, (GLenum)params[0])),
    874             GL_INVALID_ENUM);
    875 
    876     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    877         ctx->override2DTextureTarget(target);
    878         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
    879         ctx->restore2DTextureTarget();
    880     } else {
    881         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
    882     }
    883 }
    884 
    885 void GLEncoder::s_glTexParameterxv(void* self,
    886         GLenum target, GLenum pname, const GLfixed* params)
    887 {
    888     GLEncoder* ctx = (GLEncoder*)self;
    889     const GLClientState* state = ctx->m_state;
    890 
    891     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
    892             !isValidTextureExternalParam(pname, (GLenum)params[0])),
    893             GL_INVALID_ENUM);
    894 
    895     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
    896         ctx->override2DTextureTarget(target);
    897         ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
    898         ctx->restore2DTextureTarget();
    899     } else {
    900         ctx->m_glTexParameterxv_enc(ctx, target, pname, params);
    901     }
    902 }
    903 
    904 void GLEncoder::override2DTextureTarget(GLenum target)
    905 {
    906     if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
    907         target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
    908             m_glBindTexture_enc(this, GL_TEXTURE_2D,
    909                     m_state->getBoundTexture(target));
    910     }
    911 }
    912 
    913 void GLEncoder::restore2DTextureTarget()
    914 {
    915     GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
    916     m_glBindTexture_enc(this, GL_TEXTURE_2D,
    917             m_state->getBoundTexture(priorityTarget));
    918 }
    919 
    920 GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream)
    921 {
    922     m_initialized = false;
    923     m_state = NULL;
    924     m_error = GL_NO_ERROR;
    925     m_num_compressedTextureFormats = 0;
    926     m_compressedTextureFormats = NULL;
    927     // overrides;
    928     m_glFlush_enc = set_glFlush(s_glFlush);
    929     m_glPixelStorei_enc = set_glPixelStorei(s_glPixelStorei);
    930     m_glVertexPointer_enc = set_glVertexPointer(s_glVertexPointer);
    931     m_glNormalPointer_enc = set_glNormalPointer(s_glNormalPointer);
    932     m_glColorPointer_enc = set_glColorPointer(s_glColorPointer);
    933     m_glPointSizePointerOES_enc = set_glPointSizePointerOES(s_glPointsizePointer);
    934     m_glClientActiveTexture_enc = set_glClientActiveTexture(s_glClientActiveTexture);
    935     m_glTexCoordPointer_enc = set_glTexCoordPointer(s_glTexcoordPointer);
    936     m_glMatrixIndexPointerOES_enc = set_glMatrixIndexPointerOES(s_glMatrixIndexPointerOES);
    937     m_glWeightPointerOES_enc = set_glWeightPointerOES(s_glWeightPointerOES);
    938 
    939     m_glGetIntegerv_enc = set_glGetIntegerv(s_glGetIntegerv);
    940     m_glGetFloatv_enc = set_glGetFloatv(s_glGetFloatv);
    941     m_glGetBooleanv_enc = set_glGetBooleanv(s_glGetBooleanv);
    942     m_glGetFixedv_enc = set_glGetFixedv(s_glGetFixedv);
    943     m_glGetPointerv_enc = set_glGetPointerv(s_glGetPointerv);
    944 
    945     m_glBindBuffer_enc = set_glBindBuffer(s_glBindBuffer);
    946     m_glBufferData_enc = set_glBufferData(s_glBufferData);
    947     m_glBufferSubData_enc = set_glBufferSubData(s_glBufferSubData);
    948     m_glDeleteBuffers_enc = set_glDeleteBuffers(s_glDeleteBuffers);
    949 
    950     m_glEnableClientState_enc = set_glEnableClientState(s_glEnableClientState);
    951     m_glDisableClientState_enc = set_glDisableClientState(s_glDisableClientState);
    952     m_glIsEnabled_enc = set_glIsEnabled(s_glIsEnabled);
    953     m_glDrawArrays_enc = set_glDrawArrays(s_glDrawArrays);
    954     m_glDrawElements_enc = set_glDrawElements(s_glDrawElements);
    955     set_glGetString(s_glGetString);
    956     set_glFinish(s_glFinish);
    957     m_glGetError_enc = set_glGetError(s_glGetError);
    958 
    959     m_glActiveTexture_enc = set_glActiveTexture(s_glActiveTexture);
    960     m_glBindTexture_enc = set_glBindTexture(s_glBindTexture);
    961     m_glDeleteTextures_enc = set_glDeleteTextures(s_glDeleteTextures);
    962     m_glDisable_enc = set_glDisable(s_glDisable);
    963     m_glEnable_enc = set_glEnable(s_glEnable);
    964     m_glGetTexParameterfv_enc = set_glGetTexParameterfv(s_glGetTexParameterfv);
    965     m_glGetTexParameteriv_enc = set_glGetTexParameteriv(s_glGetTexParameteriv);
    966     m_glGetTexParameterxv_enc = set_glGetTexParameterxv(s_glGetTexParameterxv);
    967     m_glTexParameterf_enc = set_glTexParameterf(s_glTexParameterf);
    968     m_glTexParameterfv_enc = set_glTexParameterfv(s_glTexParameterfv);
    969     m_glTexParameteri_enc = set_glTexParameteri(s_glTexParameteri);
    970     m_glTexParameterx_enc = set_glTexParameterx(s_glTexParameterx);
    971     m_glTexParameteriv_enc = set_glTexParameteriv(s_glTexParameteriv);
    972     m_glTexParameterxv_enc = set_glTexParameterxv(s_glTexParameterxv);
    973 }
    974 
    975 GLEncoder::~GLEncoder()
    976 {
    977     delete [] m_compressedTextureFormats;
    978 }
    979 
    980 size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack)
    981 {
    982     assert(m_state != NULL);
    983     return m_state->pixelDataSize(width, height, format, type, pack);
    984 }
    985 
    986 void GLEncoder::s_glFinish(void *self)
    987 {
    988     GLEncoder *ctx = (GLEncoder *)self;
    989     ctx->glFinishRoundTrip(self);
    990 }
    991