Home | History | Annotate | Download | only in GLESv2_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 
     17 #include "GL2Encoder.h"
     18 #include <assert.h>
     19 #include <ctype.h>
     20 
     21 #ifndef MIN
     22 #define MIN(a, b) ((a) < (b) ? (a) : (b))
     23 #endif
     24 
     25 static GLubyte *gVendorString= (GLubyte *) "Android";
     26 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
     27 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
     28 static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
     29 
     30 #define SET_ERROR_IF(condition,err) if((condition)) {                            \
     31         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     32         ctx->setError(err);                                    \
     33         return;                                                  \
     34     }
     35 
     36 
     37 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
     38         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     39         ctx->setError(err);                                    \
     40         return ret;                                              \
     41     }
     42 
     43 
     44 GL2Encoder::GL2Encoder(IOStream *stream) : gl2_encoder_context_t(stream)
     45 {
     46     m_initialized = false;
     47     m_state = NULL;
     48     m_error = GL_NO_ERROR;
     49     m_num_compressedTextureFormats = 0;
     50     m_compressedTextureFormats = NULL;
     51 
     52     //overrides
     53 #define OVERRIDE(name)  m_##name##_enc = this-> name ; this-> name = &s_##name
     54 
     55     OVERRIDE(glFlush);
     56     OVERRIDE(glPixelStorei);
     57     OVERRIDE(glGetString);
     58     OVERRIDE(glBindBuffer);
     59     OVERRIDE(glBufferData);
     60     OVERRIDE(glBufferSubData);
     61     OVERRIDE(glDeleteBuffers);
     62     OVERRIDE(glDrawArrays);
     63     OVERRIDE(glDrawElements);
     64     OVERRIDE(glGetIntegerv);
     65     OVERRIDE(glGetFloatv);
     66     OVERRIDE(glGetBooleanv);
     67     OVERRIDE(glVertexAttribPointer);
     68     OVERRIDE(glEnableVertexAttribArray);
     69     OVERRIDE(glDisableVertexAttribArray);
     70     OVERRIDE(glGetVertexAttribiv);
     71     OVERRIDE(glGetVertexAttribfv);
     72     OVERRIDE(glGetVertexAttribPointerv);
     73 
     74     this->glShaderSource = &s_glShaderSource;
     75     this->glFinish = &s_glFinish;
     76 
     77     OVERRIDE(glGetError);
     78     OVERRIDE(glLinkProgram);
     79     OVERRIDE(glDeleteProgram);
     80     OVERRIDE(glGetUniformiv);
     81     OVERRIDE(glGetUniformfv);
     82     OVERRIDE(glCreateProgram);
     83     OVERRIDE(glCreateShader);
     84     OVERRIDE(glDeleteShader);
     85     OVERRIDE(glAttachShader);
     86     OVERRIDE(glDetachShader);
     87     OVERRIDE(glGetAttachedShaders);
     88     OVERRIDE(glGetShaderSource);
     89     OVERRIDE(glGetShaderInfoLog);
     90     OVERRIDE(glGetProgramInfoLog);
     91 
     92     OVERRIDE(glGetUniformLocation);
     93     OVERRIDE(glUseProgram);
     94 
     95     OVERRIDE(glUniform1f);
     96     OVERRIDE(glUniform1fv);
     97     OVERRIDE(glUniform1i);
     98     OVERRIDE(glUniform1iv);
     99     OVERRIDE(glUniform2f);
    100     OVERRIDE(glUniform2fv);
    101     OVERRIDE(glUniform2i);
    102     OVERRIDE(glUniform2iv);
    103     OVERRIDE(glUniform3f);
    104     OVERRIDE(glUniform3fv);
    105     OVERRIDE(glUniform3i);
    106     OVERRIDE(glUniform3iv);
    107     OVERRIDE(glUniform4f);
    108     OVERRIDE(glUniform4fv);
    109     OVERRIDE(glUniform4i);
    110     OVERRIDE(glUniform4iv);
    111     OVERRIDE(glUniformMatrix2fv);
    112     OVERRIDE(glUniformMatrix3fv);
    113     OVERRIDE(glUniformMatrix4fv);
    114 
    115     OVERRIDE(glActiveTexture);
    116     OVERRIDE(glBindTexture);
    117     OVERRIDE(glDeleteTextures);
    118     OVERRIDE(glGetTexParameterfv);
    119     OVERRIDE(glGetTexParameteriv);
    120     OVERRIDE(glTexParameterf);
    121     OVERRIDE(glTexParameterfv);
    122     OVERRIDE(glTexParameteri);
    123     OVERRIDE(glTexParameteriv);
    124     OVERRIDE(glTexImage2D);
    125 }
    126 
    127 GL2Encoder::~GL2Encoder()
    128 {
    129     delete m_compressedTextureFormats;
    130 }
    131 
    132 GLenum GL2Encoder::s_glGetError(void * self)
    133 {
    134     GL2Encoder *ctx = (GL2Encoder *)self;
    135     GLenum err = ctx->getError();
    136     if(err != GL_NO_ERROR) {
    137         ctx->setError(GL_NO_ERROR);
    138         return err;
    139     }
    140 
    141     return ctx->m_glGetError_enc(self);
    142 
    143 }
    144 
    145 void GL2Encoder::s_glFlush(void *self)
    146 {
    147     GL2Encoder *ctx = (GL2Encoder *) self;
    148     ctx->m_glFlush_enc(self);
    149     ctx->m_stream->flush();
    150 }
    151 
    152 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
    153 {
    154     (void)self;
    155 
    156     GLubyte *retval =  (GLubyte *) "";
    157     switch(name) {
    158     case GL_VENDOR:
    159         retval = gVendorString;
    160         break;
    161     case GL_RENDERER:
    162         retval = gRendererString;
    163         break;
    164     case GL_VERSION:
    165         retval = gVersionString;
    166         break;
    167     case GL_EXTENSIONS:
    168         retval = gExtensionsString;
    169         break;
    170     }
    171     return retval;
    172 }
    173 
    174 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
    175 {
    176     GL2Encoder *ctx = (GL2Encoder *)self;
    177     ctx->m_glPixelStorei_enc(ctx, param, value);
    178     assert(ctx->m_state != NULL);
    179     ctx->m_state->setPixelStore(param, value);
    180 }
    181 
    182 
    183 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
    184 {
    185     GL2Encoder *ctx = (GL2Encoder *) self;
    186     assert(ctx->m_state != NULL);
    187     ctx->m_state->bindBuffer(target, id);
    188     // TODO set error state if needed;
    189     ctx->m_glBindBuffer_enc(self, target, id);
    190 }
    191 
    192 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
    193 {
    194     GL2Encoder *ctx = (GL2Encoder *) self;
    195     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
    196     GLuint bufferId = ctx->m_state->getBuffer(target);
    197     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    198     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
    199 
    200     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
    201     ctx->m_glBufferData_enc(self, target, size, data, usage);
    202 }
    203 
    204 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
    205 {
    206     GL2Encoder *ctx = (GL2Encoder *) self;
    207     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
    208     GLuint bufferId = ctx->m_state->getBuffer(target);
    209     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    210 
    211     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
    212     SET_ERROR_IF(res, res);
    213 
    214     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
    215 }
    216 
    217 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
    218 {
    219     GL2Encoder *ctx = (GL2Encoder *) self;
    220     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
    221     for (int i=0; i<n; i++) {
    222         ctx->m_shared->deleteBufferData(buffers[i]);
    223         ctx->m_state->unBindBuffer(buffers[i]);
    224         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
    225     }
    226 }
    227 
    228 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
    229 {
    230     GL2Encoder *ctx = (GL2Encoder *)self;
    231     assert(ctx->m_state != NULL);
    232     ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
    233 }
    234 
    235 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
    236 {
    237     GL2Encoder *ctx = (GL2Encoder *) self;
    238     assert(ctx->m_state != NULL);
    239     GLClientState* state = ctx->m_state;
    240 
    241     switch (param) {
    242     case GL_NUM_SHADER_BINARY_FORMATS:
    243         *ptr = 0;
    244         break;
    245     case GL_SHADER_BINARY_FORMATS:
    246         // do nothing
    247         break;
    248 
    249     case GL_COMPRESSED_TEXTURE_FORMATS: {
    250         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    251         if (ctx->m_num_compressedTextureFormats > 0 &&
    252                 compressedTextureFormats != NULL) {
    253             memcpy(ptr, compressedTextureFormats,
    254                     ctx->m_num_compressedTextureFormats * sizeof(GLint));
    255         }
    256         break;
    257     }
    258 
    259     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    260     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    261     case GL_MAX_TEXTURE_IMAGE_UNITS:
    262         ctx->m_glGetIntegerv_enc(self, param, ptr);
    263         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
    264         break;
    265 
    266     case GL_TEXTURE_BINDING_2D:
    267         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
    268         break;
    269     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    270         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    271         break;
    272 
    273     default:
    274         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
    275             ctx->m_glGetIntegerv_enc(self, param, ptr);
    276         }
    277         break;
    278     }
    279 }
    280 
    281 
    282 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
    283 {
    284     GL2Encoder *ctx = (GL2Encoder *)self;
    285     assert(ctx->m_state != NULL);
    286     GLClientState* state = ctx->m_state;
    287 
    288     switch (param) {
    289     case GL_NUM_SHADER_BINARY_FORMATS:
    290         *ptr = 0;
    291         break;
    292     case GL_SHADER_BINARY_FORMATS:
    293         // do nothing
    294         break;
    295 
    296     case GL_COMPRESSED_TEXTURE_FORMATS: {
    297         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    298         if (ctx->m_num_compressedTextureFormats > 0 &&
    299                 compressedTextureFormats != NULL) {
    300             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    301                 ptr[i] = (GLfloat) compressedTextureFormats[i];
    302             }
    303         }
    304         break;
    305     }
    306 
    307     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    308     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    309     case GL_MAX_TEXTURE_IMAGE_UNITS:
    310         ctx->m_glGetFloatv_enc(self, param, ptr);
    311         *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
    312         break;
    313 
    314     case GL_TEXTURE_BINDING_2D:
    315         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
    316         break;
    317     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    318         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    319         break;
    320 
    321     default:
    322         if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
    323             ctx->m_glGetFloatv_enc(self, param, ptr);
    324         }
    325         break;
    326     }
    327 }
    328 
    329 
    330 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
    331 {
    332     GL2Encoder *ctx = (GL2Encoder *)self;
    333     assert(ctx->m_state != NULL);
    334     GLClientState* state = ctx->m_state;
    335 
    336     switch (param) {
    337     case GL_NUM_SHADER_BINARY_FORMATS:
    338         *ptr = GL_FALSE;
    339         break;
    340     case GL_SHADER_BINARY_FORMATS:
    341         // do nothing
    342         break;
    343 
    344     case GL_COMPRESSED_TEXTURE_FORMATS: {
    345         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    346         if (ctx->m_num_compressedTextureFormats > 0 &&
    347                 compressedTextureFormats != NULL) {
    348             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    349                 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
    350             }
    351         }
    352         break;
    353     }
    354 
    355     case GL_TEXTURE_BINDING_2D:
    356         *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
    357         break;
    358     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    359         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
    360                 ? GL_TRUE : GL_FALSE;
    361         break;
    362 
    363     default:
    364         if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
    365             ctx->m_glGetBooleanv_enc(self, param, ptr);
    366         }
    367         *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
    368         break;
    369     }
    370 }
    371 
    372 
    373 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
    374 {
    375     GL2Encoder *ctx = (GL2Encoder *)self;
    376     assert(ctx->m_state);
    377     ctx->m_state->enable(index, 1);
    378 }
    379 
    380 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
    381 {
    382     GL2Encoder *ctx = (GL2Encoder *)self;
    383     assert(ctx->m_state);
    384     ctx->m_state->enable(index, 0);
    385 }
    386 
    387 
    388 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
    389 {
    390     GL2Encoder *ctx = (GL2Encoder *)self;
    391     assert(ctx->m_state);
    392 
    393     if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
    394         ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
    395     }
    396 }
    397 
    398 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
    399 {
    400     GL2Encoder *ctx = (GL2Encoder *)self;
    401     assert(ctx->m_state);
    402 
    403     if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
    404         ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
    405     }
    406 }
    407 
    408 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
    409 {
    410     GL2Encoder *ctx = (GL2Encoder *)self;
    411     if (ctx->m_state == NULL) return;
    412 
    413     (void)pname;
    414 
    415     const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
    416     if (va_state != NULL) {
    417         *pointer = va_state->data;
    418     }
    419 }
    420 
    421 
    422 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
    423 {
    424     assert(m_state);
    425 
    426     for (int i = 0; i < m_state->nLocations(); i++) {
    427         bool enableDirty;
    428         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
    429 
    430         if (!state) {
    431             continue;
    432         }
    433 
    434         if (!enableDirty && !state->enabled) {
    435             continue;
    436         }
    437 
    438 
    439         if (state->enabled) {
    440             m_glEnableVertexAttribArray_enc(this, i);
    441 
    442             unsigned int datalen = state->elementSize * count;
    443             int stride = state->stride == 0 ? state->elementSize : state->stride;
    444             int firstIndex = stride * first;
    445 
    446             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
    447             if (state->bufferObject == 0) {
    448                 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
    449                                                 (unsigned char *)state->data + firstIndex, datalen);
    450             } else {
    451                 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
    452                                                   (uintptr_t) state->data + firstIndex);
    453             }
    454             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
    455         } else {
    456             this->m_glDisableVertexAttribArray_enc(this, i);
    457         }
    458     }
    459 }
    460 
    461 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
    462 {
    463     GL2Encoder *ctx = (GL2Encoder *)self;
    464     ctx->sendVertexAttributes(first, count);
    465     ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
    466 }
    467 
    468 
    469 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
    470 {
    471 
    472     GL2Encoder *ctx = (GL2Encoder *)self;
    473     assert(ctx->m_state != NULL);
    474     SET_ERROR_IF(count<0, GL_INVALID_VALUE);
    475 
    476     bool has_immediate_arrays = false;
    477     bool has_indirect_arrays = false;
    478     int nLocations = ctx->m_state->nLocations();
    479 
    480     for (int i = 0; i < nLocations; i++) {
    481         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
    482         if (state->enabled) {
    483             if (state->bufferObject != 0) {
    484                 has_indirect_arrays = true;
    485             } else {
    486                 has_immediate_arrays = true;
    487             }
    488         }
    489     }
    490 
    491     if (!has_immediate_arrays && !has_indirect_arrays) {
    492         ALOGE("glDrawElements: no data bound to the command - ignoring\n");
    493         return;
    494     }
    495 
    496     bool adjustIndices = true;
    497     if (ctx->m_state->currentIndexVbo() != 0) {
    498         if (!has_immediate_arrays) {
    499             ctx->sendVertexAttributes(0, count);
    500             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
    501             ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices);
    502             adjustIndices = false;
    503         } else {
    504             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
    505             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
    506             indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
    507         }
    508     }
    509     if (adjustIndices) {
    510         void *adjustedIndices = (void*)indices;
    511         int minIndex = 0, maxIndex = 0;
    512 
    513         switch(type) {
    514         case GL_BYTE:
    515         case GL_UNSIGNED_BYTE:
    516             GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
    517             if (minIndex != 0) {
    518                 adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
    519                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
    520                                                  (unsigned char *)adjustedIndices,
    521                                                  count, -minIndex);
    522             }
    523             break;
    524         case GL_SHORT:
    525         case GL_UNSIGNED_SHORT:
    526             GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
    527             if (minIndex != 0) {
    528                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
    529                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
    530                                                   (unsigned short *)adjustedIndices,
    531                                                   count, -minIndex);
    532             }
    533             break;
    534         default:
    535             ALOGE("unsupported index buffer type %d\n", type);
    536         }
    537         if (has_indirect_arrays || 1) {
    538             ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
    539             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
    540                                     count * glSizeof(type));
    541             // XXX - OPTIMIZATION (see the other else branch) should be implemented
    542             if(!has_indirect_arrays) {
    543                 //ALOGD("unoptimized drawelements !!!\n");
    544             }
    545         } else {
    546             // we are all direct arrays and immidate mode index array -
    547             // rebuild the arrays and the index array;
    548             ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
    549         }
    550     }
    551 }
    552 
    553 
    554 GLint * GL2Encoder::getCompressedTextureFormats()
    555 {
    556     if (m_compressedTextureFormats == NULL) {
    557         this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
    558                             &m_num_compressedTextureFormats);
    559         if (m_num_compressedTextureFormats > 0) {
    560             // get number of texture formats;
    561             m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
    562             this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
    563         }
    564     }
    565     return m_compressedTextureFormats;
    566 }
    567 
    568 // Replace uses of samplerExternalOES with sampler2D, recording the names of
    569 // modified shaders in data. Also remove
    570 //   #extension GL_OES_EGL_image_external : require
    571 // statements.
    572 //
    573 // This implementation assumes the input has already been pre-processed. If not,
    574 // a few cases will be mishandled:
    575 //
    576 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
    577 //    the following code:
    578 //      #if 1
    579 //      uniform sampler2D mySampler;
    580 //      #else
    581 //      uniform samplerExternalOES mySampler;
    582 //      #endif
    583 //
    584 // 2. Comments that look like sampler declarations will be incorrectly modified
    585 //    and recorded:
    586 //      // samplerExternalOES hahaFooledYou
    587 //
    588 // 3. However, GLSL ES does not have a concatentation operator, so things like
    589 //    this (valid in C) are invalid and not a problem:
    590 //      #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
    591 //      SAMPLER(ExternalOES, mySampler);
    592 //
    593 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
    594 {
    595     static const char STR_HASH_EXTENSION[] = "#extension";
    596     static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
    597     static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
    598     static const char STR_SAMPLER2D_SPACE[]      = "sampler2D         ";
    599 
    600     // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
    601     char* c = str;
    602     while ((c = strstr(c, STR_HASH_EXTENSION))) {
    603         char* start = c;
    604         c += sizeof(STR_HASH_EXTENSION)-1;
    605         while (isspace(*c) && *c != '\0') {
    606             c++;
    607         }
    608         if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
    609                 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
    610         {
    611             // #extension statements are terminated by end of line
    612             c = start;
    613             while (*c != '\0' && *c != '\r' && *c != '\n') {
    614                 *c++ = ' ';
    615             }
    616         }
    617     }
    618 
    619     // -- replace "samplerExternalOES" with "sampler2D" and record name
    620     c = str;
    621     while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
    622         // Make sure "samplerExternalOES" isn't a substring of a larger token
    623         if (c == str || !isspace(*(c-1))) {
    624             c++;
    625             continue;
    626         }
    627         char* sampler_start = c;
    628         c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
    629         if (!isspace(*c) && *c != '\0') {
    630             continue;
    631         }
    632 
    633         // capture sampler name
    634         while (isspace(*c) && *c != '\0') {
    635             c++;
    636         }
    637         if (!isalpha(*c) && *c != '_') {
    638             // not an identifier
    639             return false;
    640         }
    641         char* name_start = c;
    642         do {
    643             c++;
    644         } while (isalnum(*c) || *c == '_');
    645         data->samplerExternalNames.push_back(
    646                 android::String8(name_start, c - name_start));
    647 
    648         // memcpy instead of strcpy since we don't want the NUL terminator
    649         memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
    650     }
    651 
    652     return true;
    653 }
    654 
    655 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
    656 {
    657     GL2Encoder* ctx = (GL2Encoder*)self;
    658     ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
    659     SET_ERROR_IF(!shaderData, GL_INVALID_VALUE);
    660 
    661     int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
    662     char *str = new char[len + 1];
    663     glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
    664 
    665     // TODO: pre-process str before calling replaceSamplerExternalWith2D().
    666     // Perhaps we can borrow Mesa's pre-processor?
    667 
    668     if (!replaceSamplerExternalWith2D(str, shaderData)) {
    669         delete str;
    670         ctx->setError(GL_OUT_OF_MEMORY);
    671         return;
    672     }
    673 
    674     ctx->glShaderString(ctx, shader, str, len + 1);
    675     delete str;
    676 }
    677 
    678 void GL2Encoder::s_glFinish(void *self)
    679 {
    680     GL2Encoder *ctx = (GL2Encoder *)self;
    681     ctx->glFinishRoundTrip(self);
    682 }
    683 
    684 void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
    685 {
    686     GL2Encoder *ctx = (GL2Encoder *)self;
    687     ctx->m_glLinkProgram_enc(self, program);
    688 
    689     GLint linkStatus = 0;
    690     ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
    691     if (!linkStatus)
    692         return;
    693 
    694     //get number of active uniforms in the program
    695     GLint numUniforms=0;
    696     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
    697     ctx->m_shared->initProgramData(program,numUniforms);
    698 
    699     //get the length of the longest uniform name
    700     GLint maxLength=0;
    701     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
    702 
    703     GLint size;
    704     GLenum type;
    705     GLchar *name = new GLchar[maxLength+1];
    706     GLint location;
    707     //for each active uniform, get its size and starting location.
    708     for (GLint i=0 ; i<numUniforms ; ++i)
    709     {
    710         ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
    711         location = ctx->m_glGetUniformLocation_enc(self, program, name);
    712         ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
    713     }
    714     ctx->m_shared->setupLocationShiftWAR(program);
    715 
    716     delete[] name;
    717 }
    718 
    719 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
    720 {
    721     GL2Encoder *ctx = (GL2Encoder*)self;
    722     ctx->m_glDeleteProgram_enc(self, program);
    723 
    724     ctx->m_shared->deleteProgramData(program);
    725 }
    726 
    727 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
    728 {
    729     GL2Encoder *ctx = (GL2Encoder*)self;
    730     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
    731     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
    732     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
    733     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
    734     ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
    735 }
    736 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
    737 {
    738     GL2Encoder *ctx = (GL2Encoder*)self;
    739     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_VALUE);
    740     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
    741     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
    742     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
    743     ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
    744 }
    745 
    746 GLuint GL2Encoder::s_glCreateProgram(void * self)
    747 {
    748     GL2Encoder *ctx = (GL2Encoder*)self;
    749     GLuint program = ctx->m_glCreateProgram_enc(self);
    750     if (program!=0)
    751         ctx->m_shared->addProgramData(program);
    752     return program;
    753 }
    754 
    755 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
    756 {
    757     GL2Encoder *ctx = (GL2Encoder*)self;
    758     GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
    759     if (shader != 0) {
    760         if (!ctx->m_shared->addShaderData(shader)) {
    761             ctx->m_glDeleteShader_enc(self, shader);
    762             return 0;
    763         }
    764     }
    765     return shader;
    766 }
    767 
    768 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
    769         GLsizei* count, GLuint* shaders)
    770 {
    771     GL2Encoder *ctx = (GL2Encoder*)self;
    772     SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
    773     ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
    774 }
    775 
    776 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
    777             GLsizei* length, GLchar* source)
    778 {
    779     GL2Encoder *ctx = (GL2Encoder*)self;
    780     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
    781     ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
    782 }
    783 
    784 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
    785         GLsizei* length, GLchar* infolog)
    786 {
    787     GL2Encoder *ctx = (GL2Encoder*)self;
    788     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
    789     ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
    790 }
    791 
    792 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
    793         GLsizei* length, GLchar* infolog)
    794 {
    795     GL2Encoder *ctx = (GL2Encoder*)self;
    796     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
    797     ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
    798 }
    799 
    800 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
    801 {
    802     GL2Encoder *ctx = (GL2Encoder*)self;
    803     ctx->m_glDeleteShader_enc(self,shader);
    804     ctx->m_shared->unrefShaderData(shader);
    805 }
    806 
    807 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
    808 {
    809     GL2Encoder *ctx = (GL2Encoder*)self;
    810     ctx->m_glAttachShader_enc(self, program, shader);
    811     ctx->m_shared->attachShader(program, shader);
    812 }
    813 
    814 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
    815 {
    816     GL2Encoder *ctx = (GL2Encoder*)self;
    817     ctx->m_glDetachShader_enc(self, program, shader);
    818     ctx->m_shared->detachShader(program, shader);
    819 }
    820 
    821 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
    822 {
    823     if (!name) return -1;
    824 
    825     GL2Encoder *ctx = (GL2Encoder*)self;
    826 
    827     // if we need the uniform location WAR
    828     // parse array index from the end of the name string
    829     int arrIndex = 0;
    830     bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
    831     if (needLocationWAR) {
    832         int namelen = strlen(name);
    833         if (name[namelen-1] == ']') {
    834             char *brace = strrchr(name,'[');
    835             if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
    836                 return -1;
    837             }
    838 
    839         }
    840     }
    841 
    842     int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
    843     if (hostLoc >= 0 && needLocationWAR) {
    844         return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
    845     }
    846     return hostLoc;
    847 }
    848 
    849 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
    850 {
    851     if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
    852         return false;
    853 
    854     m_state->setActiveTextureUnit(texUnit);
    855 
    856     GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
    857     if (newTarget != oldTarget) {
    858         if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
    859             m_state->disableTextureTarget(GL_TEXTURE_2D);
    860             m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
    861         } else {
    862             m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
    863             m_state->enableTextureTarget(GL_TEXTURE_2D);
    864         }
    865         m_glActiveTexture_enc(this, texUnit);
    866         m_glBindTexture_enc(this, GL_TEXTURE_2D,
    867                 m_state->getBoundTexture(newTarget));
    868         return true;
    869     }
    870 
    871     return false;
    872 }
    873 
    874 void GL2Encoder::s_glUseProgram(void *self, GLuint program)
    875 {
    876     GL2Encoder *ctx = (GL2Encoder*)self;
    877     GLClientState* state = ctx->m_state;
    878     GLSharedGroupPtr shared = ctx->m_shared;
    879 
    880     ctx->m_glUseProgram_enc(self, program);
    881     ctx->m_state->setCurrentProgram(program);
    882 
    883     GLenum origActiveTexture = state->getActiveTextureUnit();
    884     GLenum hostActiveTexture = origActiveTexture;
    885     GLint samplerIdx = -1;
    886     GLint samplerVal;
    887     GLenum samplerTarget;
    888     while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
    889         if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
    890             continue;
    891         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
    892                 samplerTarget))
    893         {
    894             hostActiveTexture = GL_TEXTURE0 + samplerVal;
    895         }
    896     }
    897     state->setActiveTextureUnit(origActiveTexture);
    898     if (hostActiveTexture != origActiveTexture) {
    899         ctx->m_glActiveTexture_enc(self, origActiveTexture);
    900     }
    901 }
    902 
    903 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
    904 {
    905     GL2Encoder *ctx = (GL2Encoder*)self;
    906     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    907     ctx->m_glUniform1f_enc(self, hostLoc, x);
    908 }
    909 
    910 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
    911 {
    912     GL2Encoder *ctx = (GL2Encoder*)self;
    913     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    914     ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
    915 }
    916 
    917 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
    918 {
    919     GL2Encoder *ctx = (GL2Encoder*)self;
    920     GLClientState* state = ctx->m_state;
    921     GLSharedGroupPtr shared = ctx->m_shared;
    922 
    923     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    924     ctx->m_glUniform1i_enc(self, hostLoc, x);
    925 
    926     GLenum target;
    927     if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
    928         GLenum origActiveTexture = state->getActiveTextureUnit();
    929         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
    930             ctx->m_glActiveTexture_enc(self, origActiveTexture);
    931         }
    932         state->setActiveTextureUnit(origActiveTexture);
    933     }
    934 }
    935 
    936 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
    937 {
    938     GL2Encoder *ctx = (GL2Encoder*)self;
    939     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    940     ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
    941 }
    942 
    943 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
    944 {
    945     GL2Encoder *ctx = (GL2Encoder*)self;
    946     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    947     ctx->m_glUniform2f_enc(self, hostLoc, x, y);
    948 }
    949 
    950 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
    951 {
    952     GL2Encoder *ctx = (GL2Encoder*)self;
    953     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    954     ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
    955 }
    956 
    957 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
    958 {
    959     GL2Encoder *ctx = (GL2Encoder*)self;
    960     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    961     ctx->m_glUniform2i_enc(self, hostLoc, x, y);
    962 }
    963 
    964 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
    965 {
    966     GL2Encoder *ctx = (GL2Encoder*)self;
    967     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    968     ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
    969 }
    970 
    971 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
    972 {
    973     GL2Encoder *ctx = (GL2Encoder*)self;
    974     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    975     ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
    976 }
    977 
    978 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
    979 {
    980     GL2Encoder *ctx = (GL2Encoder*)self;
    981     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    982     ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
    983 }
    984 
    985 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
    986 {
    987     GL2Encoder *ctx = (GL2Encoder*)self;
    988     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    989     ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
    990 }
    991 
    992 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
    993 {
    994     GL2Encoder *ctx = (GL2Encoder*)self;
    995     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
    996     ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
    997 }
    998 
    999 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   1000 {
   1001     GL2Encoder *ctx = (GL2Encoder*)self;
   1002     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1003     ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
   1004 }
   1005 
   1006 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
   1007 {
   1008     GL2Encoder *ctx = (GL2Encoder*)self;
   1009     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1010     ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
   1011 }
   1012 
   1013 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
   1014 {
   1015     GL2Encoder *ctx = (GL2Encoder*)self;
   1016     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1017     ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
   1018 }
   1019 
   1020 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
   1021 {
   1022     GL2Encoder *ctx = (GL2Encoder*)self;
   1023     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1024     ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
   1025 }
   1026 
   1027 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1028 {
   1029     GL2Encoder *ctx = (GL2Encoder*)self;
   1030     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1031     ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
   1032 }
   1033 
   1034 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1035 {
   1036     GL2Encoder *ctx = (GL2Encoder*)self;
   1037     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1038     ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
   1039 }
   1040 
   1041 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1042 {
   1043     GL2Encoder *ctx = (GL2Encoder*)self;
   1044     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1045     ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
   1046 }
   1047 
   1048 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
   1049 {
   1050     GL2Encoder* ctx = (GL2Encoder*)self;
   1051     GLClientState* state = ctx->m_state;
   1052     GLenum err;
   1053 
   1054     SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
   1055 
   1056     ctx->m_glActiveTexture_enc(ctx, texture);
   1057 }
   1058 
   1059 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
   1060 {
   1061     GL2Encoder* ctx = (GL2Encoder*)self;
   1062     GLClientState* state = ctx->m_state;
   1063     GLenum err;
   1064     GLboolean firstUse;
   1065 
   1066     SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
   1067 
   1068     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
   1069         ctx->m_glBindTexture_enc(ctx, target, texture);
   1070         return;
   1071     }
   1072 
   1073     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
   1074 
   1075     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
   1076         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
   1077         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1078                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1079         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1080                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1081         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1082                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1083 
   1084         if (target != priorityTarget) {
   1085             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
   1086                     state->getBoundTexture(GL_TEXTURE_2D));
   1087         }
   1088     }
   1089 
   1090     if (target == priorityTarget) {
   1091         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
   1092     }
   1093 }
   1094 
   1095 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
   1096 {
   1097     GL2Encoder* ctx = (GL2Encoder*)self;
   1098     GLClientState* state = ctx->m_state;
   1099 
   1100     state->deleteTextures(n, textures);
   1101     ctx->m_glDeleteTextures_enc(ctx, n, textures);
   1102 }
   1103 
   1104 void GL2Encoder::s_glGetTexParameterfv(void* self,
   1105         GLenum target, GLenum pname, GLfloat* params)
   1106 {
   1107     GL2Encoder* ctx = (GL2Encoder*)self;
   1108     const GLClientState* state = ctx->m_state;
   1109 
   1110     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1111         ctx->override2DTextureTarget(target);
   1112         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1113         ctx->restore2DTextureTarget();
   1114     } else {
   1115         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
   1116     }
   1117 }
   1118 
   1119 void GL2Encoder::s_glGetTexParameteriv(void* self,
   1120         GLenum target, GLenum pname, GLint* params)
   1121 {
   1122     GL2Encoder* ctx = (GL2Encoder*)self;
   1123     const GLClientState* state = ctx->m_state;
   1124 
   1125     switch (pname) {
   1126     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
   1127         *params = 1;
   1128         break;
   1129 
   1130     default:
   1131         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1132             ctx->override2DTextureTarget(target);
   1133             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1134             ctx->restore2DTextureTarget();
   1135         } else {
   1136             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
   1137         }
   1138         break;
   1139     }
   1140 }
   1141 
   1142 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
   1143 {
   1144     switch (pname) {
   1145     case GL_TEXTURE_MIN_FILTER:
   1146     case GL_TEXTURE_MAG_FILTER:
   1147         return param == GL_NEAREST || param == GL_LINEAR;
   1148 
   1149     case GL_TEXTURE_WRAP_S:
   1150     case GL_TEXTURE_WRAP_T:
   1151         return param == GL_CLAMP_TO_EDGE;
   1152 
   1153     default:
   1154         return true;
   1155     }
   1156 }
   1157 
   1158 void GL2Encoder::s_glTexParameterf(void* self,
   1159         GLenum target, GLenum pname, GLfloat param)
   1160 {
   1161     GL2Encoder* ctx = (GL2Encoder*)self;
   1162     const GLClientState* state = ctx->m_state;
   1163 
   1164     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1165             !isValidTextureExternalParam(pname, (GLenum)param)),
   1166             GL_INVALID_ENUM);
   1167 
   1168     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1169         ctx->override2DTextureTarget(target);
   1170         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
   1171         ctx->restore2DTextureTarget();
   1172     } else {
   1173         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
   1174     }
   1175 }
   1176 
   1177 void GL2Encoder::s_glTexParameterfv(void* self,
   1178         GLenum target, GLenum pname, const GLfloat* params)
   1179 {
   1180     GL2Encoder* ctx = (GL2Encoder*)self;
   1181     const GLClientState* state = ctx->m_state;
   1182 
   1183     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1184             !isValidTextureExternalParam(pname, (GLenum)params[0])),
   1185             GL_INVALID_ENUM);
   1186 
   1187     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1188         ctx->override2DTextureTarget(target);
   1189         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1190         ctx->restore2DTextureTarget();
   1191     } else {
   1192         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
   1193     }
   1194 }
   1195 
   1196 void GL2Encoder::s_glTexParameteri(void* self,
   1197         GLenum target, GLenum pname, GLint param)
   1198 {
   1199     GL2Encoder* ctx = (GL2Encoder*)self;
   1200     const GLClientState* state = ctx->m_state;
   1201 
   1202     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1203             !isValidTextureExternalParam(pname, (GLenum)param)),
   1204             GL_INVALID_ENUM);
   1205 
   1206     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1207         ctx->override2DTextureTarget(target);
   1208         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
   1209         ctx->restore2DTextureTarget();
   1210     } else {
   1211         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
   1212     }
   1213 }
   1214 
   1215 void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
   1216         GLint internalformat, GLsizei width, GLsizei height, GLint border,
   1217         GLenum format, GLenum type, const GLvoid* pixels)
   1218 {
   1219     GL2Encoder* ctx = (GL2Encoder*)self;
   1220     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1221         ctx->override2DTextureTarget(target);
   1222         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
   1223                 height, border, format, type, pixels);
   1224         ctx->restore2DTextureTarget();
   1225     } else {
   1226         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
   1227                 height, border, format, type, pixels);
   1228     }
   1229 }
   1230 
   1231 
   1232 void GL2Encoder::s_glTexParameteriv(void* self,
   1233         GLenum target, GLenum pname, const GLint* params)
   1234 {
   1235     GL2Encoder* ctx = (GL2Encoder*)self;
   1236     const GLClientState* state = ctx->m_state;
   1237 
   1238     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1239             !isValidTextureExternalParam(pname, (GLenum)params[0])),
   1240             GL_INVALID_ENUM);
   1241 
   1242     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1243         ctx->override2DTextureTarget(target);
   1244         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1245         ctx->restore2DTextureTarget();
   1246     } else {
   1247         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
   1248     }
   1249 }
   1250 
   1251 void GL2Encoder::override2DTextureTarget(GLenum target)
   1252 {
   1253     if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
   1254         target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
   1255             m_glBindTexture_enc(this, GL_TEXTURE_2D,
   1256                     m_state->getBoundTexture(target));
   1257     }
   1258 }
   1259 
   1260 void GL2Encoder::restore2DTextureTarget()
   1261 {
   1262     GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
   1263     m_glBindTexture_enc(this, GL_TEXTURE_2D,
   1264             m_state->getBoundTexture(priorityTarget));
   1265 }
   1266