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 #include <GLES2/gl2.h>
     22 #include <GLES2/gl2ext.h>
     23 #include <GLES2/gl2platform.h>
     24 
     25 #include <GLES3/gl3.h>
     26 
     27 #ifndef MIN
     28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
     29 #endif
     30 
     31 static GLubyte *gVendorString= (GLubyte *) "Android";
     32 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
     33 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
     34 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
     35 
     36 #define SET_ERROR_IF(condition,err) if((condition)) {                            \
     37         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     38         ctx->setError(err);                                    \
     39         return;                                                  \
     40     }
     41 
     42 
     43 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
     44         ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
     45         ctx->setError(err);                                    \
     46         return ret;                                              \
     47     }
     48 
     49 
     50 GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
     51         : gl2_encoder_context_t(stream, protocol)
     52 {
     53     m_initialized = false;
     54     m_state = NULL;
     55     m_error = GL_NO_ERROR;
     56     m_num_compressedTextureFormats = 0;
     57     m_max_cubeMapTextureSize = 0;
     58     m_max_renderBufferSize = 0;
     59     m_max_textureSize = 0;
     60     m_compressedTextureFormats = NULL;
     61 
     62     //overrides
     63 #define OVERRIDE(name)  m_##name##_enc = this-> name ; this-> name = &s_##name
     64 
     65     OVERRIDE(glFlush);
     66     OVERRIDE(glPixelStorei);
     67     OVERRIDE(glGetString);
     68     OVERRIDE(glBindBuffer);
     69     OVERRIDE(glBufferData);
     70     OVERRIDE(glBufferSubData);
     71     OVERRIDE(glDeleteBuffers);
     72     OVERRIDE(glDrawArrays);
     73     OVERRIDE(glDrawElements);
     74     OVERRIDE(glGetIntegerv);
     75     OVERRIDE(glGetFloatv);
     76     OVERRIDE(glGetBooleanv);
     77     OVERRIDE(glVertexAttribPointer);
     78     OVERRIDE(glEnableVertexAttribArray);
     79     OVERRIDE(glDisableVertexAttribArray);
     80     OVERRIDE(glGetVertexAttribiv);
     81     OVERRIDE(glGetVertexAttribfv);
     82     OVERRIDE(glGetVertexAttribPointerv);
     83 
     84     this->glShaderBinary = &s_glShaderBinary;
     85     this->glShaderSource = &s_glShaderSource;
     86     this->glFinish = &s_glFinish;
     87 
     88     OVERRIDE(glGetError);
     89     OVERRIDE(glLinkProgram);
     90     OVERRIDE(glDeleteProgram);
     91     OVERRIDE(glGetUniformiv);
     92     OVERRIDE(glGetUniformfv);
     93     OVERRIDE(glCreateProgram);
     94     OVERRIDE(glCreateShader);
     95     OVERRIDE(glDeleteShader);
     96     OVERRIDE(glAttachShader);
     97     OVERRIDE(glDetachShader);
     98     OVERRIDE(glGetAttachedShaders);
     99     OVERRIDE(glGetShaderSource);
    100     OVERRIDE(glGetShaderInfoLog);
    101     OVERRIDE(glGetProgramInfoLog);
    102 
    103     OVERRIDE(glGetUniformLocation);
    104     OVERRIDE(glUseProgram);
    105 
    106     OVERRIDE(glUniform1f);
    107     OVERRIDE(glUniform1fv);
    108     OVERRIDE(glUniform1i);
    109     OVERRIDE(glUniform1iv);
    110     OVERRIDE(glUniform2f);
    111     OVERRIDE(glUniform2fv);
    112     OVERRIDE(glUniform2i);
    113     OVERRIDE(glUniform2iv);
    114     OVERRIDE(glUniform3f);
    115     OVERRIDE(glUniform3fv);
    116     OVERRIDE(glUniform3i);
    117     OVERRIDE(glUniform3iv);
    118     OVERRIDE(glUniform4f);
    119     OVERRIDE(glUniform4fv);
    120     OVERRIDE(glUniform4i);
    121     OVERRIDE(glUniform4iv);
    122     OVERRIDE(glUniformMatrix2fv);
    123     OVERRIDE(glUniformMatrix3fv);
    124     OVERRIDE(glUniformMatrix4fv);
    125 
    126     OVERRIDE(glActiveTexture);
    127     OVERRIDE(glBindTexture);
    128     OVERRIDE(glDeleteTextures);
    129     OVERRIDE(glGetTexParameterfv);
    130     OVERRIDE(glGetTexParameteriv);
    131     OVERRIDE(glTexParameterf);
    132     OVERRIDE(glTexParameterfv);
    133     OVERRIDE(glTexParameteri);
    134     OVERRIDE(glTexParameteriv);
    135     OVERRIDE(glTexImage2D);
    136     OVERRIDE(glTexSubImage2D);
    137     OVERRIDE(glCopyTexImage2D);
    138 
    139     OVERRIDE(glGenRenderbuffers);
    140     OVERRIDE(glDeleteRenderbuffers);
    141     OVERRIDE(glBindRenderbuffer);
    142     OVERRIDE(glRenderbufferStorage);
    143     OVERRIDE(glFramebufferRenderbuffer);
    144 
    145     OVERRIDE(glGenFramebuffers);
    146     OVERRIDE(glDeleteFramebuffers);
    147     OVERRIDE(glBindFramebuffer);
    148     OVERRIDE(glFramebufferTexture2D);
    149     OVERRIDE(glFramebufferTexture3DOES);
    150     OVERRIDE(glGetFramebufferAttachmentParameteriv);
    151 
    152     OVERRIDE(glCheckFramebufferStatus);
    153 }
    154 
    155 GL2Encoder::~GL2Encoder()
    156 {
    157     delete m_compressedTextureFormats;
    158 }
    159 
    160 GLenum GL2Encoder::s_glGetError(void * self)
    161 {
    162     GL2Encoder *ctx = (GL2Encoder *)self;
    163     GLenum err = ctx->getError();
    164     if(err != GL_NO_ERROR) {
    165         ctx->setError(GL_NO_ERROR);
    166         return err;
    167     }
    168 
    169     return ctx->m_glGetError_enc(self);
    170 
    171 }
    172 
    173 void GL2Encoder::s_glFlush(void *self)
    174 {
    175     GL2Encoder *ctx = (GL2Encoder *) self;
    176     ctx->m_glFlush_enc(self);
    177     ctx->m_stream->flush();
    178 }
    179 
    180 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
    181 {
    182     (void)self;
    183 
    184     GLubyte *retval =  (GLubyte *) "";
    185     switch(name) {
    186     case GL_VENDOR:
    187         retval = gVendorString;
    188         break;
    189     case GL_RENDERER:
    190         retval = gRendererString;
    191         break;
    192     case GL_VERSION:
    193         retval = gVersionString;
    194         break;
    195     case GL_EXTENSIONS:
    196         retval = gExtensionsString;
    197         break;
    198     }
    199     return retval;
    200 }
    201 
    202 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
    203 {
    204     GL2Encoder *ctx = (GL2Encoder *)self;
    205     ctx->m_glPixelStorei_enc(ctx, param, value);
    206     assert(ctx->m_state != NULL);
    207     ctx->m_state->setPixelStore(param, value);
    208 }
    209 
    210 
    211 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
    212 {
    213     GL2Encoder *ctx = (GL2Encoder *) self;
    214     assert(ctx->m_state != NULL);
    215     ctx->m_state->bindBuffer(target, id);
    216     // TODO set error state if needed;
    217     ctx->m_glBindBuffer_enc(self, target, id);
    218 }
    219 
    220 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
    221 {
    222     GL2Encoder *ctx = (GL2Encoder *) self;
    223     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
    224     GLuint bufferId = ctx->m_state->getBuffer(target);
    225     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    226     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
    227 
    228     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
    229     ctx->m_glBufferData_enc(self, target, size, data, usage);
    230 }
    231 
    232 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
    233 {
    234     GL2Encoder *ctx = (GL2Encoder *) self;
    235     SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM);
    236     GLuint bufferId = ctx->m_state->getBuffer(target);
    237     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
    238 
    239     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
    240     SET_ERROR_IF(res, res);
    241 
    242     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
    243 }
    244 
    245 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
    246 {
    247     GL2Encoder *ctx = (GL2Encoder *) self;
    248     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
    249     for (int i=0; i<n; i++) {
    250         ctx->m_shared->deleteBufferData(buffers[i]);
    251         ctx->m_state->unBindBuffer(buffers[i]);
    252         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
    253     }
    254 }
    255 
    256 static bool isValidVertexAttribIndex(void *self, GLuint indx)
    257 {
    258     GL2Encoder *ctx = (GL2Encoder *) self;
    259     GLint maxIndex;
    260     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
    261     return indx < maxIndex;
    262 }
    263 
    264 static bool isValidVertexAttribType(GLenum type)
    265 {
    266     bool retval = false;
    267     switch (type) {
    268     case GL_BYTE:
    269     case GL_UNSIGNED_BYTE:
    270     case GL_SHORT:
    271     case GL_UNSIGNED_SHORT:
    272     case GL_FIXED:
    273     case GL_FLOAT:
    274     // The following are technically only available if certain GLES2 extensions are.
    275     // However, they are supported by desktop GL3, which is a reasonable requirement
    276     // for the desktop GL version. Therefore, consider them valid.
    277     case GL_INT:
    278     case GL_UNSIGNED_INT:
    279     case GL_HALF_FLOAT_OES:
    280         retval = true;
    281         break;
    282     }
    283     return retval;
    284 }
    285 
    286 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
    287 {
    288     GL2Encoder *ctx = (GL2Encoder *)self;
    289     assert(ctx->m_state != NULL);
    290     SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE);
    291     SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE);
    292     SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM);
    293     SET_ERROR_IF(stride < 0, GL_INVALID_VALUE);
    294     ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
    295 }
    296 
    297 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
    298 {
    299     GL2Encoder *ctx = (GL2Encoder *) self;
    300     assert(ctx->m_state != NULL);
    301     GLClientState* state = ctx->m_state;
    302 
    303     switch (param) {
    304     case GL_NUM_SHADER_BINARY_FORMATS:
    305         *ptr = 0;
    306         break;
    307     case GL_SHADER_BINARY_FORMATS:
    308         // do nothing
    309         break;
    310 
    311     case GL_COMPRESSED_TEXTURE_FORMATS: {
    312         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    313         if (ctx->m_num_compressedTextureFormats > 0 &&
    314                 compressedTextureFormats != NULL) {
    315             memcpy(ptr, compressedTextureFormats,
    316                     ctx->m_num_compressedTextureFormats * sizeof(GLint));
    317         }
    318         break;
    319     }
    320 
    321     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    322     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    323     case GL_MAX_TEXTURE_IMAGE_UNITS:
    324         ctx->m_glGetIntegerv_enc(self, param, ptr);
    325         *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
    326         break;
    327 
    328     case GL_TEXTURE_BINDING_2D:
    329         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
    330         break;
    331     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    332         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    333         break;
    334 
    335     case GL_MAX_VERTEX_ATTRIBS:
    336         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
    337             ctx->m_glGetIntegerv_enc(self, param, ptr);
    338             ctx->m_state->setMaxVertexAttribs(*ptr);
    339         }
    340         break;
    341     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    342         if (ctx->m_max_cubeMapTextureSize != 0) {
    343             *ptr = ctx->m_max_cubeMapTextureSize;
    344         } else {
    345             ctx->m_glGetIntegerv_enc(self, param, ptr);
    346             ctx->m_max_cubeMapTextureSize = *ptr;
    347         }
    348         break;
    349     case GL_MAX_RENDERBUFFER_SIZE:
    350         if (ctx->m_max_renderBufferSize != 0) {
    351             *ptr = ctx->m_max_renderBufferSize;
    352         } else {
    353             ctx->m_glGetIntegerv_enc(self, param, ptr);
    354             ctx->m_max_renderBufferSize = *ptr;
    355         }
    356         break;
    357     case GL_MAX_TEXTURE_SIZE:
    358         if (ctx->m_max_textureSize != 0) {
    359             *ptr = ctx->m_max_textureSize;
    360         } else {
    361             ctx->m_glGetIntegerv_enc(self, param, ptr);
    362             ctx->m_max_textureSize = *ptr;
    363         }
    364         break;
    365     default:
    366         if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
    367             ctx->m_glGetIntegerv_enc(self, param, ptr);
    368         }
    369         break;
    370     }
    371 }
    372 
    373 
    374 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
    375 {
    376     GL2Encoder *ctx = (GL2Encoder *)self;
    377     assert(ctx->m_state != NULL);
    378     GLClientState* state = ctx->m_state;
    379 
    380     switch (param) {
    381     case GL_NUM_SHADER_BINARY_FORMATS:
    382         *ptr = 0;
    383         break;
    384     case GL_SHADER_BINARY_FORMATS:
    385         // do nothing
    386         break;
    387 
    388     case GL_COMPRESSED_TEXTURE_FORMATS: {
    389         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    390         if (ctx->m_num_compressedTextureFormats > 0 &&
    391                 compressedTextureFormats != NULL) {
    392             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    393                 ptr[i] = (GLfloat) compressedTextureFormats[i];
    394             }
    395         }
    396         break;
    397     }
    398 
    399     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    400     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    401     case GL_MAX_TEXTURE_IMAGE_UNITS:
    402         ctx->m_glGetFloatv_enc(self, param, ptr);
    403         *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
    404         break;
    405 
    406     case GL_TEXTURE_BINDING_2D:
    407         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
    408         break;
    409     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    410         *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
    411         break;
    412 
    413     default:
    414         if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
    415             ctx->m_glGetFloatv_enc(self, param, ptr);
    416         }
    417         break;
    418     }
    419 }
    420 
    421 
    422 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
    423 {
    424     GL2Encoder *ctx = (GL2Encoder *)self;
    425     assert(ctx->m_state != NULL);
    426     GLClientState* state = ctx->m_state;
    427 
    428     switch (param) {
    429     case GL_NUM_SHADER_BINARY_FORMATS:
    430         *ptr = GL_FALSE;
    431         break;
    432     case GL_SHADER_BINARY_FORMATS:
    433         // do nothing
    434         break;
    435 
    436     case GL_COMPRESSED_TEXTURE_FORMATS: {
    437         GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
    438         if (ctx->m_num_compressedTextureFormats > 0 &&
    439                 compressedTextureFormats != NULL) {
    440             for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
    441                 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
    442             }
    443         }
    444         break;
    445     }
    446 
    447     case GL_TEXTURE_BINDING_2D:
    448         *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
    449         break;
    450     case GL_TEXTURE_BINDING_EXTERNAL_OES:
    451         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
    452                 ? GL_TRUE : GL_FALSE;
    453         break;
    454 
    455     default:
    456         if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
    457             ctx->m_glGetBooleanv_enc(self, param, ptr);
    458         }
    459         *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
    460         break;
    461     }
    462 }
    463 
    464 
    465 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
    466 {
    467     GL2Encoder *ctx = (GL2Encoder *)self;
    468     assert(ctx->m_state);
    469     SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
    470     ctx->m_state->enable(index, 1);
    471 }
    472 
    473 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
    474 {
    475     GL2Encoder *ctx = (GL2Encoder *)self;
    476     assert(ctx->m_state);
    477     SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE);
    478     ctx->m_state->enable(index, 0);
    479 }
    480 
    481 
    482 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
    483 {
    484     GL2Encoder *ctx = (GL2Encoder *)self;
    485     assert(ctx->m_state);
    486     GLint maxIndex;
    487     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
    488     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
    489 
    490     if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
    491         ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
    492     }
    493 }
    494 
    495 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
    496 {
    497     GL2Encoder *ctx = (GL2Encoder *)self;
    498     assert(ctx->m_state);
    499     GLint maxIndex;
    500     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
    501     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
    502 
    503     if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
    504         ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
    505     }
    506 }
    507 
    508 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
    509 {
    510     GL2Encoder *ctx = (GL2Encoder *)self;
    511     if (ctx->m_state == NULL) return;
    512     GLint maxIndex;
    513     ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex);
    514     SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE);
    515     SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM);
    516     (void)pname;
    517 
    518     const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
    519     if (va_state != NULL) {
    520         *pointer = va_state->data;
    521     }
    522 }
    523 
    524 
    525 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
    526 {
    527     assert(m_state);
    528 
    529     GLuint lastBoundVbo = m_state->currentArrayVbo();
    530     for (int i = 0; i < m_state->nLocations(); i++) {
    531         bool enableDirty;
    532         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
    533 
    534         if (!state) {
    535             continue;
    536         }
    537 
    538         if (!enableDirty && !state->enabled) {
    539             continue;
    540         }
    541 
    542         if (state->enabled) {
    543             if (lastBoundVbo != state->bufferObject) {
    544                 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
    545                 lastBoundVbo = state->bufferObject;
    546             }
    547 
    548             unsigned int datalen = state->elementSize * count;
    549             int stride = state->stride == 0 ? state->elementSize : state->stride;
    550             int firstIndex = stride * first;
    551 
    552             if (state->bufferObject == 0) {
    553                 m_glEnableVertexAttribArray_enc(this, i);
    554                 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
    555                                                 (unsigned char *)state->data + firstIndex, datalen);
    556             } else {
    557                 const BufferData* buf = m_shared->getBufferData(state->bufferObject);
    558                 // The following expression actually means bufLen = stride*count;
    559                 // But the last element doesn't have to fill up the whole stride.
    560                 // So it becomes the current form.
    561                 unsigned int bufLen = stride * (count - 1) + state->elementSize;
    562                 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) {
    563                     m_glEnableVertexAttribArray_enc(this, i);
    564                     this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
    565                                                   (uintptr_t) state->data + firstIndex);
    566                 } else {
    567                     ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute.");
    568                     m_glDisableVertexAttribArray_enc(this, i);
    569                 }
    570             }
    571         } else {
    572             this->m_glDisableVertexAttribArray_enc(this, i);
    573         }
    574     }
    575 
    576     if (lastBoundVbo != m_state->currentArrayVbo()) {
    577         this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
    578     }
    579 }
    580 
    581 static bool isValidDrawMode(GLenum mode)
    582 {
    583     bool retval = false;
    584     switch (mode) {
    585     case GL_POINTS:
    586     case GL_LINE_STRIP:
    587     case GL_LINE_LOOP:
    588     case GL_LINES:
    589     case GL_TRIANGLE_STRIP:
    590     case GL_TRIANGLE_FAN:
    591     case GL_TRIANGLES:
    592         retval = true;
    593     }
    594     return retval;
    595 }
    596 
    597 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
    598 {
    599     GL2Encoder *ctx = (GL2Encoder *)self;
    600     assert(ctx->m_state != NULL);
    601     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
    602     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
    603 
    604     bool has_arrays = false;
    605     int nLocations = ctx->m_state->nLocations();
    606     for (int i = 0; i < nLocations; i++) {
    607         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
    608         if (state->enabled) {
    609             if (state->bufferObject || state->data)  {
    610                 has_arrays = true;
    611             }
    612             else {
    613                 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
    614                 ctx->setError(GL_INVALID_OPERATION);
    615                 return;
    616             }
    617         }
    618     }
    619 
    620     ctx->sendVertexAttributes(first, count);
    621     ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
    622     ctx->m_stream->flush();
    623 }
    624 
    625 
    626 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
    627 {
    628 
    629     GL2Encoder *ctx = (GL2Encoder *)self;
    630     assert(ctx->m_state != NULL);
    631     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
    632     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
    633     SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
    634 
    635     bool has_immediate_arrays = false;
    636     bool has_indirect_arrays = false;
    637     int nLocations = ctx->m_state->nLocations();
    638     GLintptr offset = 0;
    639 
    640     for (int i = 0; i < nLocations; i++) {
    641         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
    642         if (state->enabled) {
    643             if (state->bufferObject != 0) {
    644                 has_indirect_arrays = true;
    645             } else if (state->data) {
    646                 has_immediate_arrays = true;
    647             } else {
    648                 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n");
    649                 ctx->setError(GL_INVALID_OPERATION);
    650                 return;
    651             }
    652         }
    653     }
    654 
    655     if (!has_immediate_arrays && !has_indirect_arrays) {
    656         ALOGE("glDrawElements: no data bound to the command - ignoring\n");
    657         GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER);
    658         SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION);
    659         return;
    660     }
    661 
    662     if (ctx->m_state->currentIndexVbo() != 0) {
    663         offset = (GLintptr)indices;
    664         BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
    665         indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + offset);
    666     }
    667     int minIndex = 0, maxIndex = 0;
    668     switch(type) {
    669     case GL_BYTE:
    670     case GL_UNSIGNED_BYTE:
    671         GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
    672         break;
    673     case GL_SHORT:
    674     case GL_UNSIGNED_SHORT:
    675         GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
    676         break;
    677     case GL_INT:
    678     case GL_UNSIGNED_INT:
    679         GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
    680         break;
    681     default:
    682         ALOGE("unsupported index buffer type %d\n", type);
    683     }
    684 
    685     bool adjustIndices = true;
    686     if (ctx->m_state->currentIndexVbo() != 0) {
    687         if (!has_immediate_arrays) {
    688             ctx->sendVertexAttributes(0, maxIndex + 1);
    689             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
    690             ctx->glDrawElementsOffset(ctx, mode, count, type, offset);
    691             ctx->m_stream->flush();
    692             adjustIndices = false;
    693         } else {
    694             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
    695             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
    696         }
    697     }
    698     if (adjustIndices) {
    699         void *adjustedIndices = (void*)indices;
    700 
    701         if (minIndex != 0) {
    702             adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
    703             switch(type) {
    704             case GL_BYTE:
    705             case GL_UNSIGNED_BYTE:
    706                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
    707                                                  (unsigned char *)adjustedIndices,
    708                                                  count, -minIndex);
    709                 break;
    710             case GL_SHORT:
    711             case GL_UNSIGNED_SHORT:
    712                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
    713                                                   (unsigned short *)adjustedIndices,
    714                                                   count, -minIndex);
    715                 break;
    716             case GL_INT:
    717             case GL_UNSIGNED_INT:
    718                 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
    719                                                  (unsigned int *)adjustedIndices,
    720                                                  count, -minIndex);
    721                 break;
    722             default:
    723                 ALOGE("unsupported index buffer type %d\n", type);
    724             }
    725         }
    726         if (has_indirect_arrays || 1) {
    727             ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
    728             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
    729                                     count * glSizeof(type));
    730             ctx->m_stream->flush();
    731             // XXX - OPTIMIZATION (see the other else branch) should be implemented
    732             if(!has_indirect_arrays) {
    733                 //ALOGD("unoptimized drawelements !!!\n");
    734             }
    735         } else {
    736             // we are all direct arrays and immidate mode index array -
    737             // rebuild the arrays and the index array;
    738             ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
    739         }
    740     }
    741 }
    742 
    743 
    744 GLint * GL2Encoder::getCompressedTextureFormats()
    745 {
    746     if (m_compressedTextureFormats == NULL) {
    747         this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
    748                             &m_num_compressedTextureFormats);
    749         if (m_num_compressedTextureFormats > 0) {
    750             // get number of texture formats;
    751             m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
    752             this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
    753         }
    754     }
    755     return m_compressedTextureFormats;
    756 }
    757 
    758 // Replace uses of samplerExternalOES with sampler2D, recording the names of
    759 // modified shaders in data. Also remove
    760 //   #extension GL_OES_EGL_image_external : require
    761 // statements.
    762 //
    763 // This implementation assumes the input has already been pre-processed. If not,
    764 // a few cases will be mishandled:
    765 //
    766 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in
    767 //    the following code:
    768 //      #if 1
    769 //      uniform sampler2D mySampler;
    770 //      #else
    771 //      uniform samplerExternalOES mySampler;
    772 //      #endif
    773 //
    774 // 2. Comments that look like sampler declarations will be incorrectly modified
    775 //    and recorded:
    776 //      // samplerExternalOES hahaFooledYou
    777 //
    778 // 3. However, GLSL ES does not have a concatentation operator, so things like
    779 //    this (valid in C) are invalid and not a problem:
    780 //      #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
    781 //      SAMPLER(ExternalOES, mySampler);
    782 //
    783 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
    784 {
    785     static const char STR_HASH_EXTENSION[] = "#extension";
    786     static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
    787     static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
    788     static const char STR_SAMPLER2D_SPACE[]      = "sampler2D         ";
    789 
    790     // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
    791     char* c = str;
    792     while ((c = strstr(c, STR_HASH_EXTENSION))) {
    793         char* start = c;
    794         c += sizeof(STR_HASH_EXTENSION)-1;
    795         while (isspace(*c) && *c != '\0') {
    796             c++;
    797         }
    798         if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
    799                 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
    800         {
    801             // #extension statements are terminated by end of line
    802             c = start;
    803             while (*c != '\0' && *c != '\r' && *c != '\n') {
    804                 *c++ = ' ';
    805             }
    806         }
    807     }
    808 
    809     // -- replace "samplerExternalOES" with "sampler2D" and record name
    810     c = str;
    811     while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
    812         // Make sure "samplerExternalOES" isn't a substring of a larger token
    813         if (c == str || !isspace(*(c-1))) {
    814             c++;
    815             continue;
    816         }
    817         char* sampler_start = c;
    818         c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
    819         if (!isspace(*c) && *c != '\0') {
    820             continue;
    821         }
    822 
    823         // capture sampler name
    824         while (isspace(*c) && *c != '\0') {
    825             c++;
    826         }
    827         if (!isalpha(*c) && *c != '_') {
    828             // not an identifier
    829             return false;
    830         }
    831         char* name_start = c;
    832         do {
    833             c++;
    834         } while (isalnum(*c) || *c == '_');
    835         data->samplerExternalNames.push_back(
    836                 android::String8(name_start, c - name_start));
    837 
    838         // memcpy instead of strcpy since we don't want the NUL terminator
    839         memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
    840     }
    841 
    842     return true;
    843 }
    844 
    845 void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length)
    846 {
    847     GL2Encoder* ctx = (GL2Encoder*)self;
    848     // Although it is not supported, need to set proper error code.
    849     SET_ERROR_IF(1, GL_INVALID_ENUM);
    850 }
    851 
    852 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
    853 {
    854     GL2Encoder* ctx = (GL2Encoder*)self;
    855     ShaderData* shaderData = ctx->m_shared->getShaderData(shader);
    856     SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE);
    857     SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION);
    858     SET_ERROR_IF((count<0), GL_INVALID_VALUE);
    859 
    860     int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count);
    861     char *str = new char[len + 1];
    862     glUtilsPackStrings(str, (char**)string, (GLint*)length, count);
    863 
    864     // TODO: pre-process str before calling replaceSamplerExternalWith2D().
    865     // Perhaps we can borrow Mesa's pre-processor?
    866 
    867     if (!replaceSamplerExternalWith2D(str, shaderData)) {
    868         delete[] str;
    869         ctx->setError(GL_OUT_OF_MEMORY);
    870         return;
    871     }
    872 
    873     ctx->glShaderString(ctx, shader, str, len + 1);
    874     delete[] str;
    875 }
    876 
    877 void GL2Encoder::s_glFinish(void *self)
    878 {
    879     GL2Encoder *ctx = (GL2Encoder *)self;
    880     ctx->glFinishRoundTrip(self);
    881 }
    882 
    883 void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
    884 {
    885     GL2Encoder *ctx = (GL2Encoder *)self;
    886     ctx->m_glLinkProgram_enc(self, program);
    887 
    888     GLint linkStatus = 0;
    889     ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
    890     if (!linkStatus)
    891         return;
    892 
    893     //get number of active uniforms in the program
    894     GLint numUniforms=0;
    895     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms);
    896     ctx->m_shared->initProgramData(program,numUniforms);
    897 
    898     //get the length of the longest uniform name
    899     GLint maxLength=0;
    900     ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
    901 
    902     GLint size;
    903     GLenum type;
    904     GLchar *name = new GLchar[maxLength+1];
    905     GLint location;
    906     //for each active uniform, get its size and starting location.
    907     for (GLint i=0 ; i<numUniforms ; ++i)
    908     {
    909         ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name);
    910         location = ctx->m_glGetUniformLocation_enc(self, program, name);
    911         ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name);
    912     }
    913     ctx->m_shared->setupLocationShiftWAR(program);
    914 
    915     delete[] name;
    916 }
    917 
    918 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program)
    919 {
    920     GL2Encoder *ctx = (GL2Encoder*)self;
    921     ctx->m_glDeleteProgram_enc(self, program);
    922 
    923     ctx->m_shared->deleteProgramData(program);
    924 }
    925 
    926 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params)
    927 {
    928     GL2Encoder *ctx = (GL2Encoder*)self;
    929     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
    930     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
    931     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
    932     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location);
    933     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
    934     ctx->m_glGetUniformiv_enc(self, program, hostLoc, params);
    935 }
    936 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params)
    937 {
    938     GL2Encoder *ctx = (GL2Encoder*)self;
    939     SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE);
    940     SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION);
    941     SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION);
    942     GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location);
    943     SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION);
    944     ctx->m_glGetUniformfv_enc(self, program, hostLoc, params);
    945 }
    946 
    947 GLuint GL2Encoder::s_glCreateProgram(void * self)
    948 {
    949     GL2Encoder *ctx = (GL2Encoder*)self;
    950     GLuint program = ctx->m_glCreateProgram_enc(self);
    951     if (program!=0)
    952         ctx->m_shared->addProgramData(program);
    953     return program;
    954 }
    955 
    956 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType)
    957 {
    958     GL2Encoder *ctx = (GL2Encoder*)self;
    959     RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)),
    960         GL_INVALID_ENUM, 0);
    961     GLuint shader = ctx->m_glCreateShader_enc(self, shaderType);
    962     if (shader != 0) {
    963         if (!ctx->m_shared->addShaderData(shader)) {
    964             ctx->m_glDeleteShader_enc(self, shader);
    965             return 0;
    966         }
    967     }
    968     return shader;
    969 }
    970 
    971 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount,
    972         GLsizei* count, GLuint* shaders)
    973 {
    974     GL2Encoder *ctx = (GL2Encoder*)self;
    975     SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE);
    976     ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders);
    977 }
    978 
    979 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize,
    980             GLsizei* length, GLchar* source)
    981 {
    982     GL2Encoder *ctx = (GL2Encoder*)self;
    983     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
    984     ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source);
    985 }
    986 
    987 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize,
    988         GLsizei* length, GLchar* infolog)
    989 {
    990     GL2Encoder *ctx = (GL2Encoder*)self;
    991     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
    992     ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog);
    993 }
    994 
    995 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize,
    996         GLsizei* length, GLchar* infolog)
    997 {
    998     GL2Encoder *ctx = (GL2Encoder*)self;
    999     SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE);
   1000     ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog);
   1001 }
   1002 
   1003 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader)
   1004 {
   1005     GL2Encoder *ctx = (GL2Encoder*)self;
   1006     ctx->m_glDeleteShader_enc(self,shader);
   1007     ctx->m_shared->unrefShaderData(shader);
   1008 }
   1009 
   1010 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader)
   1011 {
   1012     GL2Encoder *ctx = (GL2Encoder*)self;
   1013     ctx->m_glAttachShader_enc(self, program, shader);
   1014     ctx->m_shared->attachShader(program, shader);
   1015 }
   1016 
   1017 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader)
   1018 {
   1019     GL2Encoder *ctx = (GL2Encoder*)self;
   1020     ctx->m_glDetachShader_enc(self, program, shader);
   1021     ctx->m_shared->detachShader(program, shader);
   1022 }
   1023 
   1024 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name)
   1025 {
   1026     if (!name) return -1;
   1027 
   1028     GL2Encoder *ctx = (GL2Encoder*)self;
   1029 
   1030     // if we need the uniform location WAR
   1031     // parse array index from the end of the name string
   1032     int arrIndex = 0;
   1033     bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program);
   1034     if (needLocationWAR) {
   1035         int namelen = strlen(name);
   1036         if (name[namelen-1] == ']') {
   1037             const char *brace = strrchr(name,'[');
   1038             if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) {
   1039                 return -1;
   1040             }
   1041 
   1042         }
   1043     }
   1044 
   1045     int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name);
   1046     if (hostLoc >= 0 && needLocationWAR) {
   1047         return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex);
   1048     }
   1049     return hostLoc;
   1050 }
   1051 
   1052 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget)
   1053 {
   1054     if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES)
   1055         return false;
   1056 
   1057     m_state->setActiveTextureUnit(texUnit);
   1058 
   1059     GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
   1060     if (newTarget != oldTarget) {
   1061         if (newTarget == GL_TEXTURE_EXTERNAL_OES) {
   1062             m_state->disableTextureTarget(GL_TEXTURE_2D);
   1063             m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
   1064         } else {
   1065             m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES);
   1066             m_state->enableTextureTarget(GL_TEXTURE_2D);
   1067         }
   1068         m_glActiveTexture_enc(this, texUnit);
   1069         m_glBindTexture_enc(this, GL_TEXTURE_2D,
   1070                 m_state->getBoundTexture(newTarget));
   1071         return true;
   1072     }
   1073 
   1074     return false;
   1075 }
   1076 
   1077 void GL2Encoder::s_glUseProgram(void *self, GLuint program)
   1078 {
   1079     GL2Encoder *ctx = (GL2Encoder*)self;
   1080     GLClientState* state = ctx->m_state;
   1081     GLSharedGroupPtr shared = ctx->m_shared;
   1082 
   1083     SET_ERROR_IF(program && !shared->isObject(program), GL_INVALID_VALUE);
   1084     SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION);
   1085 
   1086     ctx->m_glUseProgram_enc(self, program);
   1087     ctx->m_state->setCurrentProgram(program);
   1088 
   1089     GLenum origActiveTexture = state->getActiveTextureUnit();
   1090     GLenum hostActiveTexture = origActiveTexture;
   1091     GLint samplerIdx = -1;
   1092     GLint samplerVal;
   1093     GLenum samplerTarget;
   1094     while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) {
   1095         if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS)
   1096             continue;
   1097         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal,
   1098                 samplerTarget))
   1099         {
   1100             hostActiveTexture = GL_TEXTURE0 + samplerVal;
   1101         }
   1102     }
   1103     state->setActiveTextureUnit(origActiveTexture);
   1104     if (hostActiveTexture != origActiveTexture) {
   1105         ctx->m_glActiveTexture_enc(self, origActiveTexture);
   1106     }
   1107 }
   1108 
   1109 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x)
   1110 {
   1111     GL2Encoder *ctx = (GL2Encoder*)self;
   1112     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1113     ctx->m_glUniform1f_enc(self, hostLoc, x);
   1114 }
   1115 
   1116 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v)
   1117 {
   1118     GL2Encoder *ctx = (GL2Encoder*)self;
   1119     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1120     ctx->m_glUniform1fv_enc(self, hostLoc, count, v);
   1121 }
   1122 
   1123 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x)
   1124 {
   1125     GL2Encoder *ctx = (GL2Encoder*)self;
   1126     GLClientState* state = ctx->m_state;
   1127     GLSharedGroupPtr shared = ctx->m_shared;
   1128 
   1129     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1130     ctx->m_glUniform1i_enc(self, hostLoc, x);
   1131 
   1132     GLenum target;
   1133     if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) {
   1134         GLenum origActiveTexture = state->getActiveTextureUnit();
   1135         if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) {
   1136             ctx->m_glActiveTexture_enc(self, origActiveTexture);
   1137         }
   1138         state->setActiveTextureUnit(origActiveTexture);
   1139     }
   1140 }
   1141 
   1142 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v)
   1143 {
   1144     GL2Encoder *ctx = (GL2Encoder*)self;
   1145     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1146     ctx->m_glUniform1iv_enc(self, hostLoc, count, v);
   1147 }
   1148 
   1149 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y)
   1150 {
   1151     GL2Encoder *ctx = (GL2Encoder*)self;
   1152     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1153     ctx->m_glUniform2f_enc(self, hostLoc, x, y);
   1154 }
   1155 
   1156 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v)
   1157 {
   1158     GL2Encoder *ctx = (GL2Encoder*)self;
   1159     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1160     ctx->m_glUniform2fv_enc(self, hostLoc, count, v);
   1161 }
   1162 
   1163 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y)
   1164 {
   1165     GL2Encoder *ctx = (GL2Encoder*)self;
   1166     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1167     ctx->m_glUniform2i_enc(self, hostLoc, x, y);
   1168 }
   1169 
   1170 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v)
   1171 {
   1172     GL2Encoder *ctx = (GL2Encoder*)self;
   1173     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1174     ctx->m_glUniform2iv_enc(self, hostLoc, count, v);
   1175 }
   1176 
   1177 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z)
   1178 {
   1179     GL2Encoder *ctx = (GL2Encoder*)self;
   1180     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1181     ctx->m_glUniform3f_enc(self, hostLoc, x, y, z);
   1182 }
   1183 
   1184 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v)
   1185 {
   1186     GL2Encoder *ctx = (GL2Encoder*)self;
   1187     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1188     ctx->m_glUniform3fv_enc(self, hostLoc, count, v);
   1189 }
   1190 
   1191 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z)
   1192 {
   1193     GL2Encoder *ctx = (GL2Encoder*)self;
   1194     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1195     ctx->m_glUniform3i_enc(self, hostLoc, x, y, z);
   1196 }
   1197 
   1198 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v)
   1199 {
   1200     GL2Encoder *ctx = (GL2Encoder*)self;
   1201     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1202     ctx->m_glUniform3iv_enc(self, hostLoc, count, v);
   1203 }
   1204 
   1205 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   1206 {
   1207     GL2Encoder *ctx = (GL2Encoder*)self;
   1208     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1209     ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w);
   1210 }
   1211 
   1212 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v)
   1213 {
   1214     GL2Encoder *ctx = (GL2Encoder*)self;
   1215     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1216     ctx->m_glUniform4fv_enc(self, hostLoc, count, v);
   1217 }
   1218 
   1219 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w)
   1220 {
   1221     GL2Encoder *ctx = (GL2Encoder*)self;
   1222     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1223     ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w);
   1224 }
   1225 
   1226 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v)
   1227 {
   1228     GL2Encoder *ctx = (GL2Encoder*)self;
   1229     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1230     ctx->m_glUniform4iv_enc(self, hostLoc, count, v);
   1231 }
   1232 
   1233 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1234 {
   1235     GL2Encoder *ctx = (GL2Encoder*)self;
   1236     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1237     ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value);
   1238 }
   1239 
   1240 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1241 {
   1242     GL2Encoder *ctx = (GL2Encoder*)self;
   1243     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1244     ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value);
   1245 }
   1246 
   1247 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   1248 {
   1249     GL2Encoder *ctx = (GL2Encoder*)self;
   1250     GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location);
   1251     ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value);
   1252 }
   1253 
   1254 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture)
   1255 {
   1256     GL2Encoder* ctx = (GL2Encoder*)self;
   1257     GLClientState* state = ctx->m_state;
   1258     GLenum err;
   1259 
   1260     SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err);
   1261 
   1262     ctx->m_glActiveTexture_enc(ctx, texture);
   1263 }
   1264 
   1265 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
   1266 {
   1267     GL2Encoder* ctx = (GL2Encoder*)self;
   1268     GLClientState* state = ctx->m_state;
   1269     GLenum err;
   1270     GLboolean firstUse;
   1271 
   1272     SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err);
   1273 
   1274     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
   1275         ctx->m_glBindTexture_enc(ctx, target, texture);
   1276         return;
   1277     }
   1278 
   1279     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
   1280 
   1281     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
   1282         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
   1283         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1284                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1285         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1286                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1287         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
   1288                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1289 
   1290         if (target != priorityTarget) {
   1291             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
   1292                     state->getBoundTexture(GL_TEXTURE_2D));
   1293         }
   1294     }
   1295 
   1296     if (target == priorityTarget) {
   1297         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
   1298     }
   1299 }
   1300 
   1301 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
   1302 {
   1303     GL2Encoder* ctx = (GL2Encoder*)self;
   1304     GLClientState* state = ctx->m_state;
   1305 
   1306     state->deleteTextures(n, textures);
   1307     ctx->m_glDeleteTextures_enc(ctx, n, textures);
   1308 }
   1309 
   1310 void GL2Encoder::s_glGetTexParameterfv(void* self,
   1311         GLenum target, GLenum pname, GLfloat* params)
   1312 {
   1313     GL2Encoder* ctx = (GL2Encoder*)self;
   1314     const GLClientState* state = ctx->m_state;
   1315 
   1316     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1317         ctx->override2DTextureTarget(target);
   1318         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1319         ctx->restore2DTextureTarget(target);
   1320     } else {
   1321         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
   1322     }
   1323 }
   1324 
   1325 void GL2Encoder::s_glGetTexParameteriv(void* self,
   1326         GLenum target, GLenum pname, GLint* params)
   1327 {
   1328     GL2Encoder* ctx = (GL2Encoder*)self;
   1329     const GLClientState* state = ctx->m_state;
   1330 
   1331     switch (pname) {
   1332     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
   1333         *params = 1;
   1334         break;
   1335 
   1336     default:
   1337         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1338             ctx->override2DTextureTarget(target);
   1339             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1340             ctx->restore2DTextureTarget(target);
   1341         } else {
   1342             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
   1343         }
   1344         break;
   1345     }
   1346 }
   1347 
   1348 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
   1349 {
   1350     switch (pname) {
   1351     case GL_TEXTURE_MIN_FILTER:
   1352     case GL_TEXTURE_MAG_FILTER:
   1353         return param == GL_NEAREST || param == GL_LINEAR;
   1354 
   1355     case GL_TEXTURE_WRAP_S:
   1356     case GL_TEXTURE_WRAP_T:
   1357         return param == GL_CLAMP_TO_EDGE;
   1358 
   1359     default:
   1360         return true;
   1361     }
   1362 }
   1363 
   1364 void GL2Encoder::s_glTexParameterf(void* self,
   1365         GLenum target, GLenum pname, GLfloat param)
   1366 {
   1367     GL2Encoder* ctx = (GL2Encoder*)self;
   1368     const GLClientState* state = ctx->m_state;
   1369 
   1370     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1371             !isValidTextureExternalParam(pname, (GLenum)param)),
   1372             GL_INVALID_ENUM);
   1373 
   1374     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1375         ctx->override2DTextureTarget(target);
   1376         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
   1377         ctx->restore2DTextureTarget(target);
   1378     } else {
   1379         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
   1380     }
   1381 }
   1382 
   1383 void GL2Encoder::s_glTexParameterfv(void* self,
   1384         GLenum target, GLenum pname, const GLfloat* params)
   1385 {
   1386     GL2Encoder* ctx = (GL2Encoder*)self;
   1387     const GLClientState* state = ctx->m_state;
   1388 
   1389     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1390             !isValidTextureExternalParam(pname, (GLenum)params[0])),
   1391             GL_INVALID_ENUM);
   1392 
   1393     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1394         ctx->override2DTextureTarget(target);
   1395         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1396         ctx->restore2DTextureTarget(target);
   1397     } else {
   1398         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
   1399     }
   1400 }
   1401 
   1402 void GL2Encoder::s_glTexParameteri(void* self,
   1403         GLenum target, GLenum pname, GLint param)
   1404 {
   1405     GL2Encoder* ctx = (GL2Encoder*)self;
   1406     const GLClientState* state = ctx->m_state;
   1407 
   1408     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1409             !isValidTextureExternalParam(pname, (GLenum)param)),
   1410             GL_INVALID_ENUM);
   1411 
   1412     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1413         ctx->override2DTextureTarget(target);
   1414         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
   1415         ctx->restore2DTextureTarget(target);
   1416     } else {
   1417         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
   1418     }
   1419 }
   1420 
   1421 void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level,
   1422         GLint internalformat, GLsizei width, GLsizei height, GLint border,
   1423         GLenum format, GLenum type, const GLvoid* pixels)
   1424 {
   1425     GL2Encoder* ctx = (GL2Encoder*)self;
   1426     GLClientState* state = ctx->m_state;
   1427     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1428         ctx->override2DTextureTarget(target);
   1429         state->setBoundTextureInternalFormat(target, internalformat);
   1430         state->setBoundTextureFormat(target, format);
   1431         state->setBoundTextureType(target, type);
   1432 
   1433         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
   1434                 height, border, format, type, pixels);
   1435         ctx->restore2DTextureTarget(target);
   1436     } else {
   1437         ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width,
   1438                 height, border, format, type, pixels);
   1439     }
   1440 }
   1441 
   1442 void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level,
   1443         GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
   1444         GLenum type, const GLvoid* pixels)
   1445 {
   1446     GL2Encoder* ctx = (GL2Encoder*)self;
   1447 
   1448     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1449         ctx->override2DTextureTarget(target);
   1450         ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
   1451                 height, format, type, pixels);
   1452         ctx->restore2DTextureTarget(target);
   1453     } else {
   1454         ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width,
   1455                 height, format, type, pixels);
   1456     }
   1457 }
   1458 
   1459 void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level,
   1460         GLenum internalformat, GLint x, GLint y,
   1461         GLsizei width, GLsizei height, GLint border)
   1462 {
   1463     GL2Encoder* ctx = (GL2Encoder*)self;
   1464     GLClientState* state = ctx->m_state;
   1465 
   1466     // This is needed to work around underlying OpenGL drivers
   1467     // (such as those feeding some some AMD GPUs) that expect
   1468     // positive components of cube maps to be defined _before_
   1469     // the negative components (otherwise a segfault occurs).
   1470     GLenum extraTarget =
   1471         state->copyTexImageLuminanceCubeMapAMDWorkaround
   1472             (target, level, internalformat);
   1473 
   1474     if (extraTarget) {
   1475         ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat,
   1476                                     x, y, width, height, border);
   1477     }
   1478 
   1479     ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat,
   1480                                 x, y, width, height, border);
   1481 }
   1482 
   1483 void GL2Encoder::s_glTexParameteriv(void* self,
   1484         GLenum target, GLenum pname, const GLint* params)
   1485 {
   1486     GL2Encoder* ctx = (GL2Encoder*)self;
   1487     const GLClientState* state = ctx->m_state;
   1488 
   1489     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
   1490             !isValidTextureExternalParam(pname, (GLenum)params[0])),
   1491             GL_INVALID_ENUM);
   1492 
   1493     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
   1494         ctx->override2DTextureTarget(target);
   1495         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
   1496         ctx->restore2DTextureTarget(target);
   1497     } else {
   1498         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
   1499     }
   1500 }
   1501 
   1502 bool GL2Encoder::texture2DNeedsOverride(GLenum target) const {
   1503     return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
   1504            target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
   1505 }
   1506 
   1507 void GL2Encoder::override2DTextureTarget(GLenum target)
   1508 {
   1509     if (texture2DNeedsOverride(target)) {
   1510         m_glBindTexture_enc(this, GL_TEXTURE_2D,
   1511                 m_state->getBoundTexture(target));
   1512     }
   1513 }
   1514 
   1515 void GL2Encoder::restore2DTextureTarget(GLenum target)
   1516 {
   1517     if (texture2DNeedsOverride(target)) {
   1518         m_glBindTexture_enc(this, GL_TEXTURE_2D,
   1519                 m_state->getBoundTexture(
   1520                     m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)));
   1521     }
   1522 }
   1523 
   1524 void GL2Encoder::s_glGenRenderbuffers(void* self,
   1525         GLsizei n, GLuint* renderbuffers) {
   1526     GL2Encoder* ctx = (GL2Encoder*)self;
   1527     GLClientState* state = ctx->m_state;
   1528 
   1529     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
   1530 
   1531     ctx->m_glGenFramebuffers_enc(self, n, renderbuffers);
   1532     state->addRenderbuffers(n, renderbuffers);
   1533 }
   1534 
   1535 void GL2Encoder::s_glDeleteRenderbuffers(void* self,
   1536         GLsizei n, const GLuint* renderbuffers) {
   1537     GL2Encoder* ctx = (GL2Encoder*)self;
   1538     GLClientState* state = ctx->m_state;
   1539 
   1540     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
   1541 
   1542     ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers);
   1543     state->removeRenderbuffers(n, renderbuffers);
   1544 }
   1545 
   1546 void GL2Encoder::s_glBindRenderbuffer(void* self,
   1547         GLenum target, GLuint renderbuffer) {
   1548     GL2Encoder* ctx = (GL2Encoder*)self;
   1549     GLClientState* state = ctx->m_state;
   1550 
   1551     SET_ERROR_IF((target != GL_RENDERBUFFER),
   1552                  GL_INVALID_ENUM);
   1553 
   1554     ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer);
   1555     state->bindRenderbuffer(target, renderbuffer);
   1556 }
   1557 
   1558 void GL2Encoder::s_glRenderbufferStorage(void* self,
   1559         GLenum target, GLenum internalformat,
   1560         GLsizei width, GLsizei height) {
   1561     GL2Encoder* ctx = (GL2Encoder*) self;
   1562     GLClientState* state = ctx->m_state;
   1563 
   1564     SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM);
   1565     switch (internalformat) {
   1566     // Funny internal formats
   1567     // that will cause an incomplete framebuffer
   1568     // attachment error. For dEQP,
   1569     // we can also just abort early here in
   1570     // RenderbufferStorage with a GL_INVALID_ENUM.
   1571     case GL_DEPTH_COMPONENT32F:
   1572     case GL_R8:
   1573     case GL_R8UI:
   1574     case GL_R8I:
   1575     case GL_R16UI:
   1576     case GL_R16I:
   1577     case GL_R32UI:
   1578     case GL_R32I:
   1579     case GL_RG8:
   1580     case GL_RG8UI:
   1581     case GL_RG8I:
   1582     case GL_RG16UI:
   1583     case GL_RG16I:
   1584     case GL_RG32UI:
   1585     case GL_RG32I:
   1586     case GL_SRGB8_ALPHA8:
   1587     case GL_RGBA8UI:
   1588     case GL_RGBA8I:
   1589     case GL_RGB10_A2UI:
   1590     case GL_RGBA16UI:
   1591     case GL_RGBA16I:
   1592     case GL_RGBA32I:
   1593     case GL_RGBA32UI:
   1594     case GL_R11F_G11F_B10F:
   1595     case GL_R32F:
   1596     case GL_RG32F:
   1597     case GL_RGB32F:
   1598     case GL_RGBA32F:
   1599         SET_ERROR_IF(true, GL_INVALID_ENUM);
   1600         break;
   1601     // These 4 formats are still not OK,
   1602     // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
   1603     // GL_FRAMEBUFFER_UNSUPPORTED,
   1604     // not a GL_INVALID_ENUM from earlier on.
   1605     // So let's forward these to the rest of
   1606     // FBO initialization
   1607     case GL_R16F:
   1608     case GL_RG16F:
   1609     case GL_RGB16F:
   1610     case GL_RGBA16F:
   1611     // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
   1612     // for this format
   1613     case GL_RGB10_A2:
   1614     // These formats are OK
   1615     case GL_DEPTH_COMPONENT16:
   1616     case GL_DEPTH_COMPONENT24:
   1617     case GL_DEPTH_COMPONENT32_OES:
   1618     case GL_RGBA4:
   1619     case GL_RGB5_A1:
   1620     case GL_RGB565:
   1621     case GL_RGB8_OES:
   1622     case GL_RGBA8_OES:
   1623     case GL_STENCIL_INDEX8:
   1624     case GL_DEPTH32F_STENCIL8:
   1625     case GL_DEPTH24_STENCIL8_OES:
   1626         break;
   1627     // Everything else: still not OK,
   1628     // and they need the GL_INVALID_ENUM
   1629     default:
   1630         SET_ERROR_IF(true, GL_INVALID_ENUM);
   1631     }
   1632 
   1633     state->setBoundRenderbufferFormat(internalformat);
   1634     ctx->m_glRenderbufferStorage_enc(self, target, internalformat,
   1635                                      width, height);
   1636 }
   1637 
   1638 void GL2Encoder::s_glFramebufferRenderbuffer(void* self,
   1639         GLenum target, GLenum attachment,
   1640         GLenum renderbuffertarget, GLuint renderbuffer) {
   1641     GL2Encoder* ctx = (GL2Encoder*)self;
   1642     GLClientState* state = ctx->m_state;
   1643 
   1644     state->attachRbo(attachment, renderbuffer);
   1645 
   1646     ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer);
   1647 }
   1648 
   1649 void GL2Encoder::s_glGenFramebuffers(void* self,
   1650         GLsizei n, GLuint* framebuffers) {
   1651     GL2Encoder* ctx = (GL2Encoder*)self;
   1652     GLClientState* state = ctx->m_state;
   1653 
   1654     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
   1655 
   1656     ctx->m_glGenFramebuffers_enc(self, n, framebuffers);
   1657     state->addFramebuffers(n, framebuffers);
   1658 }
   1659 
   1660 void GL2Encoder::s_glDeleteFramebuffers(void* self,
   1661         GLsizei n, const GLuint* framebuffers) {
   1662     GL2Encoder* ctx = (GL2Encoder*)self;
   1663     GLClientState* state = ctx->m_state;
   1664 
   1665     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
   1666 
   1667     ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers);
   1668     state->removeFramebuffers(n, framebuffers);
   1669 }
   1670 
   1671 void GL2Encoder::s_glBindFramebuffer(void* self,
   1672         GLenum target, GLuint framebuffer) {
   1673     GL2Encoder* ctx = (GL2Encoder*)self;
   1674     GLClientState* state = ctx->m_state;
   1675 
   1676     SET_ERROR_IF((target != GL_FRAMEBUFFER),
   1677                  GL_INVALID_ENUM);
   1678 
   1679     state->bindFramebuffer(target, framebuffer);
   1680 
   1681     ctx->m_glBindFramebuffer_enc(self, target, framebuffer);
   1682 }
   1683 
   1684 void GL2Encoder::s_glFramebufferTexture2D(void* self,
   1685         GLenum target, GLenum attachment,
   1686         GLenum textarget, GLuint texture, GLint level) {
   1687     GL2Encoder* ctx = (GL2Encoder*)self;
   1688     GLClientState* state = ctx->m_state;
   1689 
   1690     state->attachTextureObject(attachment, texture);
   1691 
   1692     ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level);
   1693 }
   1694 
   1695 void GL2Encoder::s_glFramebufferTexture3DOES(void* self,
   1696         GLenum target, GLenum attachment,
   1697         GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
   1698     GL2Encoder* ctx = (GL2Encoder*)self;
   1699     GLClientState* state = ctx->m_state;
   1700 
   1701     state->attachTextureObject(attachment, texture);
   1702 
   1703     ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset);
   1704 }
   1705 
   1706 void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self,
   1707         GLenum target, GLenum attachment, GLenum pname, GLint* params) {
   1708     GL2Encoder* ctx = (GL2Encoder*)self;
   1709     const GLClientState* state = ctx->m_state;
   1710 
   1711     SET_ERROR_IF(state->boundFramebuffer() == 0,
   1712                  GL_INVALID_OPERATION);
   1713     SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
   1714                  (!state->attachmentHasObject(attachment)),
   1715                  GL_INVALID_ENUM);
   1716 
   1717     ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params);
   1718 }
   1719 
   1720 bool GL2Encoder::isCompleteFbo(const GLClientState* state,
   1721                                GLenum attachment) const {
   1722     FboFormatInfo fbo_format_info;
   1723     state->getBoundFramebufferFormat(attachment, &fbo_format_info);
   1724 
   1725     bool res;
   1726     switch (fbo_format_info.type) {
   1727     case FBO_ATTACHMENT_RENDERBUFFER:
   1728         switch (fbo_format_info.rb_format) {
   1729         case GL_R16F:
   1730         case GL_RG16F:
   1731         case GL_RGB16F:
   1732         case GL_RGBA16F:
   1733             res = false;
   1734             break;
   1735         case GL_STENCIL_INDEX8:
   1736             if (attachment == GL_STENCIL_ATTACHMENT) {
   1737                 res = true;
   1738             } else {
   1739                 res = false;
   1740             }
   1741             break;
   1742         default:
   1743             res = true;
   1744         }
   1745         break;
   1746     case FBO_ATTACHMENT_TEXTURE:
   1747         switch (fbo_format_info.tex_internalformat) {
   1748         case GL_RED:
   1749         case GL_RG:
   1750         case GL_R16F:
   1751         case GL_RG16F:
   1752         case GL_RGBA16F:
   1753         case GL_RGB16F:
   1754         case GL_R11F_G11F_B10F:
   1755             res = false;
   1756             break;
   1757         // No float/half-float formats allowed for RGB(A)
   1758         case GL_RGB:
   1759         case GL_RGBA:
   1760             switch (fbo_format_info.tex_type) {
   1761             case GL_FLOAT:
   1762             case GL_HALF_FLOAT_OES:
   1763             case GL_UNSIGNED_INT_10F_11F_11F_REV:
   1764                 res = false;
   1765                 break;
   1766             default:
   1767                 res = true;
   1768             }
   1769             break;
   1770         default:
   1771             res = true;
   1772         }
   1773         break;
   1774     case FBO_ATTACHMENT_NONE:
   1775         res = true;
   1776         break;
   1777     default:
   1778         res = true;
   1779     }
   1780     return res;
   1781 }
   1782 
   1783 GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) {
   1784     GL2Encoder* ctx = (GL2Encoder*)self;
   1785     GLClientState* state = ctx->m_state;
   1786 
   1787     bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) &&
   1788                     ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) &&
   1789                     ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT);
   1790     if (!complete) {
   1791         state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
   1792         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
   1793     } else {
   1794         GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target);
   1795         state->setCheckFramebufferStatus(host_checkstatus);
   1796         return host_checkstatus;
   1797     }
   1798 }
   1799