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