Home | History | Annotate | Download | only in OpenglCodecCommon
      1 /*
      2 * Copyright (C) 2011 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 #include "GLClientState.h"
     17 #include "GLESTextureUtils.h"
     18 #include "ErrorLog.h"
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include "glUtils.h"
     23 #include <cutils/log.h>
     24 
     25 #ifndef MAX
     26 #define MAX(a, b) ((a) < (b) ? (b) : (a))
     27 #endif
     28 
     29 // Don't include these in the .h file, or we get weird compile errors.
     30 #include <GLES3/gl3.h>
     31 #include <GLES3/gl31.h>
     32 
     33 void GLClientState::init() {
     34     m_initialized = false;
     35     m_nLocations = CODEC_MAX_VERTEX_ATTRIBUTES;
     36 
     37     m_arrayBuffer = 0;
     38     m_max_vertex_attrib_bindings = m_nLocations;
     39     addVertexArrayObject(0);
     40     setVertexArrayObject(0);
     41     // init gl constans;
     42     m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
     43     m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
     44     m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
     45     m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
     46     m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     47     m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     48     m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     49     m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     50     m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     51     m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     52     m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     53     m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
     54     m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
     55     m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
     56 
     57     m_copyReadBuffer = 0;
     58     m_copyWriteBuffer = 0;
     59     m_pixelPackBuffer = 0;
     60     m_pixelUnpackBuffer = 0;
     61     m_transformFeedbackBuffer = 0;
     62     m_uniformBuffer = 0;
     63     m_atomicCounterBuffer = 0;
     64     m_dispatchIndirectBuffer = 0;
     65     m_drawIndirectBuffer = 0;
     66     m_shaderStorageBuffer = 0;
     67 
     68     m_transformFeedbackActiveUnpaused = false;
     69 
     70     // to be modified later when these are queried from host.
     71     m_max_transform_feedback_separate_attribs = 0;
     72     m_max_uniform_buffer_bindings = 0;
     73     m_max_atomic_counter_buffer_bindings = 0;
     74     m_max_shader_storage_buffer_bindings = 0;
     75 
     76     m_activeTexture = 0;
     77     m_currentProgram = 0;
     78     m_currentShaderProgram = 0;
     79 
     80     m_pixelStore.unpack_alignment = 4;
     81     m_pixelStore.pack_alignment = 4;
     82 
     83     m_pixelStore.unpack_row_length = 0;
     84     m_pixelStore.unpack_image_height = 0;
     85     m_pixelStore.unpack_skip_pixels = 0;
     86     m_pixelStore.unpack_skip_rows = 0;
     87     m_pixelStore.unpack_skip_images = 0;
     88 
     89     m_pixelStore.pack_row_length = 0;
     90     m_pixelStore.pack_skip_pixels = 0;
     91     m_pixelStore.pack_skip_rows = 0;
     92 
     93     memset(m_tex.unit, 0, sizeof(m_tex.unit));
     94     m_tex.activeUnit = &m_tex.unit[0];
     95     m_tex.textureRecs = NULL;
     96 
     97     mRboState.boundRenderbuffer = 0;
     98     mRboState.boundRenderbufferIndex = 0;
     99 
    100     mFboState.boundDrawFramebuffer = 0;
    101     mFboState.boundReadFramebuffer = 0;
    102     mFboState.drawFboCheckStatus = GL_NONE;
    103     mFboState.readFboCheckStatus = GL_NONE;
    104 
    105     m_maxVertexAttribsDirty = true;
    106 }
    107 
    108 GLClientState::GLClientState()
    109 {
    110     init();
    111 }
    112 
    113 GLClientState::GLClientState(int majorVersion, int minorVersion) :
    114     m_glesMajorVersion(majorVersion),
    115     m_glesMinorVersion(minorVersion) {
    116     init();
    117 }
    118 
    119 GLClientState::~GLClientState()
    120 {
    121 }
    122 
    123 void GLClientState::enable(int location, int state)
    124 {
    125     m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
    126     m_currVaoState[location].enabled = state;
    127 }
    128 
    129 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
    130 {
    131     m_currVaoState[location].size = size;
    132     m_currVaoState[location].type = type;
    133     m_currVaoState[location].stride = stride;
    134     m_currVaoState[location].data = (void*)data;
    135     m_currVaoState[location].bufferObject = m_arrayBuffer;
    136     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
    137     switch (type) {
    138         case GL_INT_2_10_10_10_REV:
    139         case GL_UNSIGNED_INT_2_10_10_10_REV:
    140             m_currVaoState[location].elementSize =
    141                 m_currVaoState[location].elementSize / 4;
    142             break;
    143         default:
    144             break;
    145     }
    146     m_currVaoState[location].normalized = normalized;
    147     m_currVaoState[location].isInt = isInt;
    148 }
    149 
    150 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
    151     m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
    152 }
    153 
    154 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
    155     return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
    156 }
    157 
    158 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
    159     m_currVaoState[attribindex].bindingindex = bindingindex;
    160 }
    161 
    162 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
    163     m_currVaoState[location].size = size;
    164     m_currVaoState[location].type = type;
    165     m_currVaoState[location].normalized = normalized;
    166     m_currVaoState[location].reloffset = reloffset;
    167     m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
    168     switch (type) {
    169         case GL_INT_2_10_10_10_REV:
    170         case GL_UNSIGNED_INT_2_10_10_10_REV:
    171             m_currVaoState[location].elementSize =
    172                 m_currVaoState[location].elementSize / 4;
    173             break;
    174         default:
    175             break;
    176     }
    177     m_currVaoState[location].isInt = isInt;
    178 }
    179 
    180 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
    181     for (GLsizei i = 0; i < n; i++) {
    182         addVertexArrayObject(arrays[i]);
    183     }
    184 }
    185 
    186 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
    187     for (GLsizei i = 0; i < n; i++) {
    188         if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
    189             setVertexArrayObject(0);
    190         }
    191         removeVertexArrayObject(arrays[i]);
    192     }
    193 }
    194 
    195 void GLClientState::addVertexArrayObject(GLuint name) {
    196     if (m_vaoMap.find(name) !=
    197         m_vaoMap.end()) {
    198         ALOGE("%s: ERROR: %u already part of current VAO state!",
    199               __FUNCTION__, name);
    200         return;
    201     }
    202 
    203     m_vaoMap.insert(
    204             VAOStateMap::value_type(
    205                 name,
    206                 VAOState(0, m_nLocations, std::max(m_nLocations, m_max_vertex_attrib_bindings))));
    207     VertexAttribStateVector& attribState =
    208         m_vaoMap.find(name)->second.attribState;
    209     for (int i = 0; i < m_nLocations; i++) {
    210         attribState[i].enabled = 0;
    211         attribState[i].enableDirty = false;
    212         attribState[i].data = 0;
    213         attribState[i].reloffset = 0;
    214         attribState[i].bindingindex = i;
    215         attribState[i].divisor = 0;
    216         attribState[i].size = 4; // 4 is the default size
    217         attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
    218     }
    219 
    220     VertexAttribBindingVector& bindingState =
    221         m_vaoMap.find(name)->second.bindingState;
    222     for (int i = 0; i < bindingState.size(); i++) {
    223         bindingState[i].effectiveStride = 16;
    224     }
    225 }
    226 
    227 void GLClientState::removeVertexArrayObject(GLuint name) {
    228     if (name == 0) {
    229         ALOGE("%s: ERROR: cannot delete VAO 0!",
    230               __FUNCTION__);
    231         return;
    232     }
    233     if (m_vaoMap.find(name) ==
    234         m_vaoMap.end()) {
    235         ALOGE("%s: ERROR: %u not found in VAO state!",
    236               __FUNCTION__, name);
    237         return;
    238     }
    239     m_vaoMap.erase(name);
    240 }
    241 
    242 void GLClientState::setVertexArrayObject(GLuint name) {
    243     if (m_vaoMap.find(name) ==
    244         m_vaoMap.end()) {
    245         ALOGE("%s: ERROR: %u not found in VAO state!",
    246               __FUNCTION__, name);
    247         return;
    248     }
    249 
    250     if (name && m_currVaoState.vaoId() == name) {
    251         ALOGV("%s: set vao to self, no-op (%u)",
    252               __FUNCTION__, name);
    253         return;
    254     }
    255 
    256     m_currVaoState =
    257         VAOStateRef(m_vaoMap.find(name));
    258     ALOGV("%s: set vao to %u (%u) %u %u", __FUNCTION__,
    259             name,
    260             m_currVaoState.vaoId(),
    261             m_arrayBuffer,
    262             m_currVaoState.iboId());
    263 }
    264 
    265 bool GLClientState::isVertexArrayObject(GLuint vao) const {
    266     return m_vaoMap.find(vao) != m_vaoMap.end();
    267 }
    268 
    269 const GLClientState::VertexAttribState& GLClientState::getState(int location)
    270 {
    271     return m_currVaoState[location];
    272 }
    273 
    274 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
    275 {
    276     if (enableChanged) {
    277         *enableChanged = m_currVaoState[location].enableDirty;
    278     }
    279 
    280     m_currVaoState[location].enableDirty = false;
    281     return m_currVaoState[location];
    282 }
    283 
    284 int GLClientState::getLocation(GLenum loc)
    285 {
    286     int retval;
    287 
    288     switch(loc) {
    289     case GL_VERTEX_ARRAY:
    290         retval = int(VERTEX_LOCATION);
    291         break;
    292     case GL_NORMAL_ARRAY:
    293         retval = int(NORMAL_LOCATION);
    294         break;
    295     case GL_COLOR_ARRAY:
    296         retval = int(COLOR_LOCATION);
    297         break;
    298     case GL_POINT_SIZE_ARRAY_OES:
    299         retval = int(POINTSIZE_LOCATION);
    300         break;
    301     case GL_TEXTURE_COORD_ARRAY:
    302         retval = int (TEXCOORD0_LOCATION + m_activeTexture);
    303         break;
    304     case GL_MATRIX_INDEX_ARRAY_OES:
    305         retval = int (MATRIXINDEX_LOCATION);
    306         break;
    307     case GL_WEIGHT_ARRAY_OES:
    308         retval = int (WEIGHT_LOCATION);
    309         break;
    310     default:
    311         retval = loc;
    312     }
    313     return retval;
    314 }
    315 
    316 static void sClearIndexedBufferBinding(GLuint id, std::vector<GLClientState::BufferBinding>& bindings) {
    317     for (size_t i = 0; i < bindings.size(); i++) {
    318         if (bindings[i].buffer == id) {
    319             bindings[i].offset = 0;
    320             bindings[i].stride = 0;
    321             bindings[i].effectiveStride = 16;
    322             bindings[i].size = 0;
    323             bindings[i].buffer = 0;
    324             bindings[i].divisor = 0;
    325         }
    326     }
    327 }
    328 
    329 void GLClientState::addBuffer(GLuint id) {
    330     mBufferIds.insert(id);
    331 }
    332 
    333 void GLClientState::removeBuffer(GLuint id) {
    334     mBufferIds.erase(id);
    335 }
    336 
    337 bool GLClientState::bufferIdExists(GLuint id) const {
    338     return mBufferIds.find(id) != mBufferIds.end();
    339 }
    340 
    341 void GLClientState::unBindBuffer(GLuint id) {
    342     if (m_arrayBuffer == id) m_arrayBuffer = 0;
    343     if (m_currVaoState.iboId() == id) m_currVaoState.iboId() = 0;
    344     if (m_copyReadBuffer == id)
    345         m_copyReadBuffer = 0;
    346     if (m_copyWriteBuffer == id)
    347         m_copyWriteBuffer = 0;
    348     if (m_pixelPackBuffer == id)
    349         m_pixelPackBuffer = 0;
    350     if (m_pixelUnpackBuffer == id)
    351         m_pixelUnpackBuffer = 0;
    352     if (m_transformFeedbackBuffer == id)
    353         m_transformFeedbackBuffer = 0;
    354     if (m_uniformBuffer == id)
    355         m_uniformBuffer = 0;
    356     if (m_atomicCounterBuffer == id)
    357         m_atomicCounterBuffer = 0;
    358     if (m_dispatchIndirectBuffer == id)
    359         m_dispatchIndirectBuffer = 0;
    360     if (m_drawIndirectBuffer == id)
    361         m_drawIndirectBuffer = 0;
    362     if (m_shaderStorageBuffer == id)
    363         m_shaderStorageBuffer = 0;
    364 
    365     sClearIndexedBufferBinding(id, m_indexedTransformFeedbackBuffers);
    366     sClearIndexedBufferBinding(id, m_indexedUniformBuffers);
    367     sClearIndexedBufferBinding(id, m_indexedAtomicCounterBuffers);
    368     sClearIndexedBufferBinding(id, m_indexedShaderStorageBuffers);
    369     sClearIndexedBufferBinding(id, m_currVaoState.bufferBindings());
    370 }
    371 
    372 int GLClientState::bindBuffer(GLenum target, GLuint id)
    373 {
    374     int err = 0;
    375     switch(target) {
    376     case GL_ARRAY_BUFFER:
    377         m_arrayBuffer = id;
    378         break;
    379     case GL_ELEMENT_ARRAY_BUFFER:
    380         m_currVaoState.iboId() = id;
    381         break;
    382     case GL_COPY_READ_BUFFER:
    383         m_copyReadBuffer = id;
    384         break;
    385     case GL_COPY_WRITE_BUFFER:
    386         m_copyWriteBuffer = id;
    387         break;
    388     case GL_PIXEL_PACK_BUFFER:
    389         m_pixelPackBuffer = id;
    390         break;
    391     case GL_PIXEL_UNPACK_BUFFER:
    392         m_pixelUnpackBuffer = id;
    393         break;
    394     case GL_TRANSFORM_FEEDBACK_BUFFER:
    395         m_transformFeedbackBuffer = id;
    396         break;
    397     case GL_UNIFORM_BUFFER:
    398         m_uniformBuffer = id;
    399         break;
    400     case GL_ATOMIC_COUNTER_BUFFER:
    401         m_atomicCounterBuffer = id;
    402         break;
    403     case GL_DISPATCH_INDIRECT_BUFFER:
    404         m_dispatchIndirectBuffer = id;
    405         break;
    406     case GL_DRAW_INDIRECT_BUFFER:
    407         m_drawIndirectBuffer = id;
    408         break;
    409     case GL_SHADER_STORAGE_BUFFER:
    410         m_shaderStorageBuffer = id;
    411         break;
    412     default:
    413         err = -1;
    414     }
    415     return err;
    416 }
    417 
    418 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
    419     switch (target) {
    420     case GL_TRANSFORM_FEEDBACK_BUFFER:
    421         m_indexedTransformFeedbackBuffers[index].buffer = buffer;
    422         m_indexedTransformFeedbackBuffers[index].offset = offset;
    423         m_indexedTransformFeedbackBuffers[index].size = size;
    424         m_indexedTransformFeedbackBuffers[index].stride = stride;
    425         break;
    426     case GL_UNIFORM_BUFFER:
    427         m_indexedUniformBuffers[index].buffer = buffer;
    428         m_indexedUniformBuffers[index].offset = offset;
    429         m_indexedUniformBuffers[index].size = size;
    430         m_indexedUniformBuffers[index].stride = stride;
    431         break;
    432     case GL_ATOMIC_COUNTER_BUFFER:
    433         m_indexedAtomicCounterBuffers[index].buffer = buffer;
    434         m_indexedAtomicCounterBuffers[index].offset = offset;
    435         m_indexedAtomicCounterBuffers[index].size = size;
    436         m_indexedAtomicCounterBuffers[index].stride = stride;
    437         break;
    438     case GL_SHADER_STORAGE_BUFFER:
    439         m_indexedShaderStorageBuffers[index].buffer = buffer;
    440         m_indexedShaderStorageBuffers[index].offset = offset;
    441         m_indexedShaderStorageBuffers[index].size = size;
    442         m_indexedShaderStorageBuffers[index].stride = stride;
    443         break;
    444     default:
    445         m_currVaoState.bufferBinding(index).buffer = buffer;
    446         m_currVaoState.bufferBinding(index).offset = offset;
    447         m_currVaoState.bufferBinding(index).size = size;
    448         m_currVaoState.bufferBinding(index).stride = stride;
    449         m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
    450         return;
    451     }
    452 }
    453 
    454 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
    455     switch (target) {
    456     case GL_TRANSFORM_FEEDBACK_BUFFER:
    457         return m_indexedTransformFeedbackBuffers.size();
    458     case GL_UNIFORM_BUFFER:
    459         return m_indexedUniformBuffers.size();
    460     case GL_ATOMIC_COUNTER_BUFFER:
    461         return m_indexedAtomicCounterBuffers.size();
    462     case GL_SHADER_STORAGE_BUFFER:
    463         return m_indexedShaderStorageBuffers.size();
    464     default:
    465         return m_currVaoState.bufferBindings_const().size();
    466     }
    467 }
    468 
    469 int GLClientState::getBuffer(GLenum target) {
    470     int ret=0;
    471     switch (target) {
    472         case GL_ARRAY_BUFFER:
    473             ret = m_arrayBuffer;
    474             break;
    475         case GL_ELEMENT_ARRAY_BUFFER:
    476             ret = m_currVaoState.iboId();
    477             break;
    478         case GL_COPY_READ_BUFFER:
    479             ret = m_copyReadBuffer;
    480             break;
    481         case GL_COPY_WRITE_BUFFER:
    482             ret = m_copyWriteBuffer;
    483             break;
    484         case GL_PIXEL_PACK_BUFFER:
    485             ret = m_pixelPackBuffer;
    486             break;
    487         case GL_PIXEL_UNPACK_BUFFER:
    488             ret = m_pixelUnpackBuffer;
    489             break;
    490         case GL_TRANSFORM_FEEDBACK_BUFFER:
    491             ret = m_transformFeedbackBuffer;
    492             break;
    493         case GL_UNIFORM_BUFFER:
    494             ret = m_uniformBuffer;
    495             break;
    496         case GL_ATOMIC_COUNTER_BUFFER:
    497             ret = m_atomicCounterBuffer;
    498             break;
    499         case GL_DISPATCH_INDIRECT_BUFFER:
    500             ret = m_dispatchIndirectBuffer;
    501             break;
    502         case GL_DRAW_INDIRECT_BUFFER:
    503             ret = m_drawIndirectBuffer;
    504             break;
    505         case GL_SHADER_STORAGE_BUFFER:
    506             ret = m_shaderStorageBuffer;
    507             break;
    508         default:
    509             ret = -1;
    510     }
    511     return ret;
    512 }
    513 
    514 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
    515 {
    516     GLenum which_state = -1;
    517     switch (pname) {
    518     case GL_VERTEX_ARRAY_POINTER: {
    519         which_state = GLClientState::VERTEX_LOCATION;
    520         break;
    521         }
    522     case GL_NORMAL_ARRAY_POINTER: {
    523         which_state = GLClientState::NORMAL_LOCATION;
    524         break;
    525         }
    526     case GL_COLOR_ARRAY_POINTER: {
    527         which_state = GLClientState::COLOR_LOCATION;
    528         break;
    529         }
    530     case GL_TEXTURE_COORD_ARRAY_POINTER: {
    531         which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
    532         break;
    533         }
    534     case GL_POINT_SIZE_ARRAY_POINTER_OES: {
    535         which_state = GLClientState::POINTSIZE_LOCATION;
    536         break;
    537         }
    538     case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
    539         which_state = GLClientState::MATRIXINDEX_LOCATION;
    540         break;
    541         }
    542     case GL_WEIGHT_ARRAY_POINTER_OES: {
    543         which_state = GLClientState::WEIGHT_LOCATION;
    544         break;
    545         }
    546     }
    547     if (which_state != -1)
    548         *params = getState(which_state).data;
    549 }
    550 
    551 int GLClientState::setPixelStore(GLenum param, GLint value)
    552 {
    553     int retval = 0;
    554     switch(param) {
    555     case GL_UNPACK_ALIGNMENT:
    556         m_pixelStore.unpack_alignment = value;
    557         break;
    558     case GL_PACK_ALIGNMENT:
    559         m_pixelStore.pack_alignment = value;
    560         break;
    561     case GL_UNPACK_ROW_LENGTH:
    562         m_pixelStore.unpack_row_length = value;
    563         break;
    564     case GL_UNPACK_IMAGE_HEIGHT:
    565         m_pixelStore.unpack_image_height = value;
    566         break;
    567     case GL_UNPACK_SKIP_PIXELS:
    568         m_pixelStore.unpack_skip_pixels = value;
    569         break;
    570     case GL_UNPACK_SKIP_ROWS:
    571         m_pixelStore.unpack_skip_rows = value;
    572         break;
    573     case GL_UNPACK_SKIP_IMAGES:
    574         m_pixelStore.unpack_skip_images = value;
    575         break;
    576     case GL_PACK_ROW_LENGTH:
    577         m_pixelStore.pack_row_length = value;
    578         break;
    579     case GL_PACK_SKIP_PIXELS:
    580         m_pixelStore.pack_skip_pixels = value;
    581         break;
    582     case GL_PACK_SKIP_ROWS:
    583         m_pixelStore.pack_skip_rows = value;
    584         break;
    585     default:
    586         retval = GL_INVALID_ENUM;
    587     }
    588     return retval;
    589 }
    590 
    591 
    592 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
    593 {
    594     if (width <= 0 || height <= 0 || depth <= 0) return 0;
    595 
    596     ALOGV("%s: pack? %d", __FUNCTION__, pack);
    597     if (pack) {
    598         ALOGV("%s: pack stats", __FUNCTION__);
    599         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
    600         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
    601         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
    602         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
    603     } else {
    604         ALOGV("%s: unpack stats", __FUNCTION__);
    605         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
    606         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
    607         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
    608         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
    609         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
    610         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
    611     }
    612     return GLESTextureUtils::computeTotalImageSize(
    613             width, height, depth,
    614             format, type,
    615             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
    616             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
    617             pack ? 0 : m_pixelStore.unpack_image_height,
    618             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
    619             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
    620             pack ? 0 : m_pixelStore.unpack_skip_images);
    621 }
    622 
    623 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
    624 {
    625     if (width <= 0 || height <= 0 || depth <= 0) return 0;
    626 
    627     ALOGV("%s: pack? %d", __FUNCTION__, pack);
    628     if (pack) {
    629         ALOGV("%s: pack stats", __FUNCTION__);
    630         ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
    631         ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
    632         ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
    633         ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
    634     } else {
    635         ALOGV("%s: unpack stats", __FUNCTION__);
    636         ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
    637         ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
    638         ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
    639         ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
    640         ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
    641         ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
    642     }
    643     return GLESTextureUtils::computeNeededBufferSize(
    644             width, height, depth,
    645             format, type,
    646             pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
    647             pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
    648             pack ? 0 : m_pixelStore.unpack_image_height,
    649             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
    650             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
    651             pack ? 0 : m_pixelStore.unpack_skip_images);
    652 }
    653 
    654 
    655 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
    656 {
    657     switch (buffer) {
    658     case GL_COLOR:
    659         return 4;
    660     case GL_DEPTH:
    661     case GL_STENCIL:
    662         return 1;
    663     }
    664     return 1;
    665 }
    666 
    667 void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
    668 {
    669     if (width <= 0 || height <= 0) {
    670         *startOffset = 0;
    671         *pixelRowSize = 0;
    672         *totalRowSize = 0;
    673         return;
    674     }
    675 
    676     GLESTextureUtils::computePackingOffsets2D(
    677             width, height,
    678             format, type,
    679             m_pixelStore.pack_alignment,
    680             m_pixelStore.pack_row_length,
    681             m_pixelStore.pack_skip_pixels,
    682             m_pixelStore.pack_skip_rows,
    683             startOffset,
    684             pixelRowSize,
    685             totalRowSize);
    686 
    687     *skipRows = m_pixelStore.pack_skip_rows;
    688 }
    689 
    690 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
    691     UniformBlockInfoKey key;
    692     key.program = program;
    693     key.uniformBlockIndex = uniformBlockIndex;
    694 
    695     UniformBlockUniformInfo info;
    696     info.numActiveUniforms = (size_t)numActiveUniforms;
    697 
    698     m_uniformBlockInfoMap[key] = info;
    699 }
    700 
    701 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
    702     UniformBlockInfoKey key;
    703     key.program = program;
    704     key.uniformBlockIndex = uniformBlockIndex;
    705     UniformBlockInfoMap::const_iterator it =
    706         m_uniformBlockInfoMap.find(key);
    707     if (it == m_uniformBlockInfoMap.end()) return 0;
    708     return it->second.numActiveUniforms;
    709 }
    710 
    711 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
    712     m_programPipelines[program] = pipeline;
    713 }
    714 
    715 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
    716     return m_programPipelines.begin();
    717 }
    718 
    719 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
    720     return m_programPipelines.end();
    721 }
    722 
    723 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
    724 {
    725     GLuint unit = texture - GL_TEXTURE0;
    726     if (unit >= MAX_TEXTURE_UNITS) {
    727         return GL_INVALID_ENUM;
    728     }
    729     m_tex.activeUnit = &m_tex.unit[unit];
    730     return GL_NO_ERROR;
    731 }
    732 
    733 GLenum GLClientState::getActiveTextureUnit() const
    734 {
    735     return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
    736 }
    737 
    738 void GLClientState::enableTextureTarget(GLenum target)
    739 {
    740     switch (target) {
    741     case GL_TEXTURE_2D:
    742         m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
    743         break;
    744     case GL_TEXTURE_EXTERNAL_OES:
    745         m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
    746         break;
    747     }
    748 }
    749 
    750 void GLClientState::disableTextureTarget(GLenum target)
    751 {
    752     switch (target) {
    753     case GL_TEXTURE_2D:
    754         m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
    755         break;
    756     case GL_TEXTURE_EXTERNAL_OES:
    757         m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
    758         break;
    759     }
    760 }
    761 
    762 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
    763 {
    764     unsigned int enables = m_tex.activeUnit->enables;
    765     if (enables & (1u << TEXTURE_EXTERNAL)) {
    766         return GL_TEXTURE_EXTERNAL_OES;
    767     } else if (enables & (1u << TEXTURE_2D)) {
    768         return GL_TEXTURE_2D;
    769     } else {
    770         return allDisabled;
    771     }
    772 }
    773 
    774 int GLClientState::compareTexId(const void* pid, const void* prec)
    775 {
    776     const GLuint* id = (const GLuint*)pid;
    777     const TextureRec* rec = (const TextureRec*)prec;
    778     return (GLint)(*id) - (GLint)rec->id;
    779 }
    780 
    781 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
    782         GLboolean* firstUse)
    783 {
    784     GLboolean first = GL_FALSE;
    785 
    786     TextureRec* texrec = getTextureRec(texture);
    787     if (!texrec) {
    788         texrec = addTextureRec(texture, target);
    789     }
    790 
    791     if (texture && target != texrec->target &&
    792         (target != GL_TEXTURE_EXTERNAL_OES &&
    793          texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
    794         ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
    795     }
    796 
    797     switch (target) {
    798     case GL_TEXTURE_2D:
    799         m_tex.activeUnit->texture[TEXTURE_2D] = texture;
    800         break;
    801     case GL_TEXTURE_EXTERNAL_OES:
    802         m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
    803         break;
    804     case GL_TEXTURE_CUBE_MAP:
    805         m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
    806         break;
    807     case GL_TEXTURE_2D_ARRAY:
    808         m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
    809         break;
    810     case GL_TEXTURE_3D:
    811         m_tex.activeUnit->texture[TEXTURE_3D] = texture;
    812         break;
    813     case GL_TEXTURE_2D_MULTISAMPLE:
    814         m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
    815         break;
    816     }
    817 
    818     if (firstUse) {
    819         *firstUse = first;
    820     }
    821 
    822     return GL_NO_ERROR;
    823 }
    824 
    825 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
    826     GLuint texture = getBoundTexture(target);
    827     TextureRec* texrec = getTextureRec(texture);
    828     if (!texrec) return;
    829     texrec->boundEGLImage = true;
    830 }
    831 
    832 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
    833 {
    834     TextureRec* tex = new TextureRec;
    835     tex->id = id;
    836     tex->target = target;
    837     tex->format = -1;
    838     tex->multisamples = 0;
    839     tex->immutable = false;
    840     tex->boundEGLImage = false;
    841     tex->dims = new TextureDims;
    842 
    843     (*(m_tex.textureRecs))[id] = tex;
    844     return tex;
    845 }
    846 
    847 TextureRec* GLClientState::getTextureRec(GLuint id) const {
    848     SharedTextureDataMap::const_iterator it =
    849         m_tex.textureRecs->find(id);
    850     if (it == m_tex.textureRecs->end()) {
    851         return NULL;
    852     }
    853     return it->second;
    854 }
    855 
    856 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
    857     GLuint texture = getBoundTexture(target);
    858     TextureRec* texrec = getTextureRec(texture);
    859     if (!texrec) return;
    860     texrec->internalformat = internalformat;
    861 }
    862 
    863 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
    864     GLuint texture = getBoundTexture(target);
    865     TextureRec* texrec = getTextureRec(texture);
    866     if (!texrec) return;
    867     texrec->format = format;
    868 }
    869 
    870 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
    871     GLuint texture = getBoundTexture(target);
    872     TextureRec* texrec = getTextureRec(texture);
    873     if (!texrec) return;
    874     texrec->type = type;
    875 }
    876 
    877 void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
    878     GLuint texture = getBoundTexture(target);
    879     TextureRec* texrec = getTextureRec(texture);
    880     if (!texrec) {
    881         return;
    882     }
    883 
    884     if (level == -1) {
    885         GLsizei curr_width = width;
    886         GLsizei curr_height = height;
    887         GLsizei curr_depth = depth;
    888         GLsizei curr_level = 0;
    889 
    890         while (true) {
    891             texrec->dims->widths[curr_level] = curr_width;
    892             texrec->dims->heights[curr_level] = curr_height;
    893             texrec->dims->depths[curr_level] = curr_depth;
    894             if (curr_width >> 1 == 0 &&
    895                 curr_height >> 1 == 0 &&
    896                 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
    897                  true)) {
    898                 break;
    899             }
    900             curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
    901             curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
    902             if (target == GL_TEXTURE_3D) {
    903                 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
    904             }
    905             curr_level++;
    906         }
    907 
    908     } else {
    909         texrec->dims->widths[level] = width;
    910         texrec->dims->heights[level] = height;
    911         texrec->dims->depths[level] = depth;
    912     }
    913 }
    914 
    915 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
    916     GLuint texture = getBoundTexture(target);
    917     TextureRec* texrec = getTextureRec(texture);
    918     if (!texrec) return;
    919     texrec->multisamples = samples;
    920 }
    921 
    922 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
    923     GLuint texture = getBoundTexture(target);
    924     TextureRec* texrec = getTextureRec(texture);
    925     if (!texrec) return;
    926     texrec->immutable = true;
    927 }
    928 
    929 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
    930     GLuint texture = getBoundTexture(target);
    931     TextureRec* texrec = getTextureRec(texture);
    932     if (!texrec) return false;
    933     return texrec->immutable;
    934 }
    935 
    936 GLuint GLClientState::getBoundTexture(GLenum target) const
    937 {
    938     switch (target) {
    939     case GL_TEXTURE_2D:
    940         return m_tex.activeUnit->texture[TEXTURE_2D];
    941     case GL_TEXTURE_EXTERNAL_OES:
    942         return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
    943     case GL_TEXTURE_CUBE_MAP:
    944         return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
    945     case GL_TEXTURE_2D_ARRAY:
    946         return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
    947     case GL_TEXTURE_3D:
    948         return m_tex.activeUnit->texture[TEXTURE_3D];
    949     case GL_TEXTURE_2D_MULTISAMPLE:
    950         return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
    951     default:
    952         return 0;
    953     }
    954 }
    955 
    956 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    957 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
    958 
    959 static bool unreliableInternalFormat(GLenum internalformat) {
    960     switch (internalformat) {
    961     case GL_LUMINANCE:
    962         return true;
    963     default:
    964         return false;
    965     }
    966 }
    967 
    968 void GLClientState::writeCopyTexImageState
    969     (GLenum target, GLint level, GLenum internalformat) {
    970     if (unreliableInternalFormat(internalformat)) {
    971         CubeMapDef entry;
    972         entry.id = getBoundTexture(GL_TEXTURE_2D);
    973         entry.target = target;
    974         entry.level = level;
    975         entry.internalformat = internalformat;
    976         m_cubeMapDefs.insert(entry);
    977     }
    978 }
    979 
    980 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
    981     switch (target) {
    982     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    983         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
    984     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    985         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
    986     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    987         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
    988     default:
    989         return 0;
    990     }
    991 }
    992 
    993 GLenum GLClientState::copyTexImageNeededTarget
    994     (GLenum target, GLint level, GLenum internalformat) {
    995     if (unreliableInternalFormat(internalformat)) {
    996         GLenum positiveComponent =
    997             identifyPositiveCubeMapComponent(target);
    998         if (positiveComponent) {
    999             CubeMapDef query;
   1000             query.id = getBoundTexture(GL_TEXTURE_2D);
   1001             query.target = positiveComponent;
   1002             query.level = level;
   1003             query.internalformat = internalformat;
   1004             if (m_cubeMapDefs.find(query) ==
   1005                 m_cubeMapDefs.end()) {
   1006                 return positiveComponent;
   1007             }
   1008         }
   1009     }
   1010     return 0;
   1011 }
   1012 
   1013 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
   1014     (GLenum target, GLint level, GLenum internalformat) {
   1015     writeCopyTexImageState(target, level, internalformat);
   1016     return copyTexImageNeededTarget(target, level, internalformat);
   1017 }
   1018 
   1019 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
   1020 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
   1021 
   1022 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
   1023 {
   1024     // Updating the textures array could be made more efficient when deleting
   1025     // several textures:
   1026     // - compacting the array could be done in a single pass once the deleted
   1027     //   textures are marked, or
   1028     // - could swap deleted textures to the end and re-sort.
   1029     TextureRec* texrec;
   1030     for (const GLuint* texture = textures; texture != textures + n; texture++) {
   1031         texrec = getTextureRec(*texture);
   1032         if (texrec && texrec->dims) {
   1033             delete texrec->dims;
   1034         }
   1035         if (texrec) {
   1036             m_tex.textureRecs->erase(*texture);
   1037             delete texrec;
   1038             for (TextureUnit* unit = m_tex.unit;
   1039                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
   1040                  unit++)
   1041             {
   1042                 if (unit->texture[TEXTURE_2D] == *texture) {
   1043                     unit->texture[TEXTURE_2D] = 0;
   1044                 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
   1045                     unit->texture[TEXTURE_EXTERNAL] = 0;
   1046                 }
   1047             }
   1048         }
   1049     }
   1050 }
   1051 
   1052 // RBO//////////////////////////////////////////////////////////////////////////
   1053 
   1054 void GLClientState::addFreshRenderbuffer(GLuint name) {
   1055     // if underlying opengl says these are fresh names,
   1056     // but we are keeping a stale one, reset it.
   1057     RboProps props;
   1058     props.target = GL_RENDERBUFFER;
   1059     props.name = name;
   1060     props.format = GL_NONE;
   1061     props.multisamples = 0;
   1062     props.previouslyBound = false;
   1063 
   1064     if (usedRenderbufferName(name)) {
   1065         mRboState.rboData[getRboIndex(name)] = props;
   1066     } else {
   1067         mRboState.rboData.push_back(props);
   1068     }
   1069 }
   1070 
   1071 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
   1072     for (size_t i = 0; i < n; i++) {
   1073         addFreshRenderbuffer(renderbuffers[i]);
   1074     }
   1075 }
   1076 
   1077 size_t GLClientState::getRboIndex(GLuint name) const {
   1078     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1079         if (mRboState.rboData[i].name == name) {
   1080             return i;
   1081         }
   1082     }
   1083     return -1;
   1084 }
   1085 
   1086 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
   1087     size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
   1088 
   1089     std::vector<GLuint> to_remove;
   1090     for (size_t i = 0; i < n; i++) {
   1091         if (renderbuffers[i] != 0) { // Never remove the zero rb.
   1092             to_remove.push_back(getRboIndex(renderbuffers[i]));
   1093         }
   1094     }
   1095 
   1096     for (size_t i = 0; i < to_remove.size(); i++) {
   1097         mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
   1098         mRboState.rboData.pop_back();
   1099     }
   1100 
   1101     // If we just deleted the currently bound rb,
   1102     // bind the zero rb
   1103     if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
   1104         bindRenderbuffer(GL_RENDERBUFFER, 0);
   1105     }
   1106 }
   1107 
   1108 bool GLClientState::usedRenderbufferName(GLuint name) const {
   1109     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1110         if (mRboState.rboData[i].name == name) {
   1111             return true;
   1112         }
   1113     }
   1114     return false;
   1115 }
   1116 
   1117 void GLClientState::setBoundRenderbufferIndex() {
   1118     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1119         if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
   1120             mRboState.boundRenderbufferIndex = i;
   1121             break;
   1122         }
   1123     }
   1124 }
   1125 
   1126 RboProps& GLClientState::boundRboProps() {
   1127     return mRboState.rboData[mRboState.boundRenderbufferIndex];
   1128 }
   1129 
   1130 const RboProps& GLClientState::boundRboProps_const() const {
   1131     return mRboState.rboData[mRboState.boundRenderbufferIndex];
   1132 }
   1133 
   1134 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
   1135     // If unused, add it.
   1136     if (!usedRenderbufferName(name)) {
   1137         addFreshRenderbuffer(name);
   1138     }
   1139     mRboState.boundRenderbuffer = name;
   1140     setBoundRenderbufferIndex();
   1141     boundRboProps().target = target;
   1142     boundRboProps().previouslyBound = true;
   1143 }
   1144 
   1145 GLuint GLClientState::boundRenderbuffer() const {
   1146     return boundRboProps_const().name;
   1147 }
   1148 
   1149 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
   1150     boundRboProps().format = format;
   1151 }
   1152 
   1153 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
   1154     boundRboProps().multisamples = samples;
   1155 }
   1156 
   1157 // FBO//////////////////////////////////////////////////////////////////////////
   1158 
   1159 // Format querying
   1160 
   1161 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
   1162     return mRboState.rboData[getRboIndex(rbo_name)].format;
   1163 }
   1164 
   1165 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
   1166     return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
   1167 }
   1168 
   1169 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
   1170     TextureRec* texrec = getTextureRec(tex_name);
   1171     if (!texrec) return -1;
   1172     return texrec->internalformat;
   1173 }
   1174 
   1175 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
   1176     TextureRec* texrec = getTextureRec(tex_name);
   1177     if (!texrec) {
   1178         return 0;
   1179     }
   1180     return texrec->dims->widths[level];
   1181 }
   1182 
   1183 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
   1184     TextureRec* texrec = getTextureRec(tex_name);
   1185     if (!texrec) return 0;
   1186     return texrec->dims->heights[level];
   1187 }
   1188 
   1189 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
   1190     TextureRec* texrec = getTextureRec(tex_name);
   1191     if (!texrec) return 0;
   1192     return texrec->dims->depths[level];
   1193 }
   1194 
   1195 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
   1196     TextureRec* texrec = getTextureRec(tex_name);
   1197     if (!texrec) return false;
   1198     return texrec->boundEGLImage;
   1199 }
   1200 
   1201 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
   1202     TextureRec* texrec = getTextureRec(tex_name);
   1203     if (!texrec) return -1;
   1204     return texrec->format;
   1205 }
   1206 
   1207 GLenum GLClientState::queryTexType(GLuint tex_name) const {
   1208     TextureRec* texrec = getTextureRec(tex_name);
   1209     if (!texrec) return -1;
   1210     return texrec->type;
   1211 }
   1212 
   1213 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
   1214     TextureRec* texrec = getTextureRec(tex_name);
   1215     if (!texrec) return 0;
   1216     return texrec->multisamples;
   1217 }
   1218 
   1219 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
   1220     TextureRec* texrec = getTextureRec(tex_name);
   1221     if (!texrec) return GL_NONE;
   1222     return texrec->target;
   1223 }
   1224 
   1225 void GLClientState::getBoundFramebufferFormat(
   1226         GLenum target,
   1227         GLenum attachment, FboFormatInfo* res_info) const {
   1228     const FboProps& props = boundFboProps_const(target);
   1229 
   1230     res_info->type = FBO_ATTACHMENT_NONE;
   1231     res_info->rb_format = GL_NONE;
   1232     res_info->rb_multisamples = 0;
   1233     res_info->tex_internalformat = -1;
   1234     res_info->tex_format = GL_NONE;
   1235     res_info->tex_type = GL_NONE;
   1236     res_info->tex_multisamples = 0;
   1237 
   1238     int colorAttachmentIndex =
   1239         glUtilsColorAttachmentIndex(attachment);
   1240 
   1241     if (colorAttachmentIndex != -1) {
   1242         if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
   1243             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1244             res_info->rb_format =
   1245                 queryRboFormat(
   1246                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1247             res_info->rb_multisamples =
   1248                 queryRboSamples(
   1249                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1250         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
   1251             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1252             res_info->tex_internalformat =
   1253                 queryTexInternalFormat(
   1254                         props.colorAttachmenti_textures[colorAttachmentIndex]);
   1255             res_info->tex_format =
   1256                 queryTexFormat(
   1257                         props.colorAttachmenti_textures[colorAttachmentIndex]);
   1258             res_info->tex_type =
   1259                 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1260             res_info->tex_multisamples =
   1261                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1262         } else {
   1263             res_info->type = FBO_ATTACHMENT_NONE;
   1264         }
   1265     }
   1266 
   1267     switch (attachment) {
   1268     case GL_DEPTH_ATTACHMENT:
   1269         if (props.depthAttachment_hasRbo) {
   1270             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1271             res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
   1272             res_info->rb_multisamples =
   1273                 queryRboSamples(
   1274                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1275         } else if (props.depthAttachment_hasTexObj) {
   1276             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1277             res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
   1278             res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
   1279             res_info->tex_type = queryTexType(props.depthAttachment_texture);
   1280             res_info->tex_multisamples =
   1281                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1282         } else {
   1283             res_info->type = FBO_ATTACHMENT_NONE;
   1284         }
   1285         break;
   1286     case GL_STENCIL_ATTACHMENT:
   1287         if (props.stencilAttachment_hasRbo) {
   1288             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1289             res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
   1290             res_info->rb_multisamples =
   1291                 queryRboSamples(
   1292                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1293         } else if (props.stencilAttachment_hasTexObj) {
   1294             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1295             res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
   1296             res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
   1297             res_info->tex_type = queryTexType(props.stencilAttachment_texture);
   1298             res_info->tex_multisamples =
   1299                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1300         } else {
   1301             res_info->type = FBO_ATTACHMENT_NONE;
   1302         }
   1303         break;
   1304     case GL_DEPTH_STENCIL_ATTACHMENT:
   1305         if (props.depthstencilAttachment_hasRbo) {
   1306             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1307             res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
   1308             res_info->rb_multisamples =
   1309                 queryRboSamples(
   1310                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1311         } else if (props.depthstencilAttachment_hasTexObj) {
   1312             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1313             res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
   1314             res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
   1315             res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
   1316             res_info->tex_multisamples =
   1317                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1318         } else {
   1319             res_info->type = FBO_ATTACHMENT_NONE;
   1320         }
   1321         break;
   1322     }
   1323 }
   1324 
   1325 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
   1326     FboFormatInfo info;
   1327     getBoundFramebufferFormat(target, attachment, &info);
   1328     return info.type;
   1329 }
   1330 
   1331 
   1332 int GLClientState::getMaxColorAttachments() const {
   1333     return m_max_color_attachments;
   1334 }
   1335 
   1336 int GLClientState::getMaxDrawBuffers() const {
   1337     return m_max_draw_buffers;
   1338 }
   1339 
   1340 void GLClientState::addFreshFramebuffer(GLuint name) {
   1341     FboProps props;
   1342     props.name = name;
   1343     props.previouslyBound = false;
   1344 
   1345     props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
   1346     props.depthAttachment_texture = 0;
   1347     props.stencilAttachment_texture = 0;
   1348     props.depthstencilAttachment_texture = 0;
   1349 
   1350     props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
   1351     props.depthAttachment_hasTexObj = false;
   1352     props.stencilAttachment_hasTexObj = false;
   1353     props.depthstencilAttachment_hasTexObj = false;
   1354 
   1355     props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
   1356     props.depthAttachment_rbo = 0;
   1357     props.stencilAttachment_rbo = 0;
   1358     props.depthstencilAttachment_rbo = 0;
   1359 
   1360     props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
   1361     props.depthAttachment_hasRbo = false;
   1362     props.stencilAttachment_hasRbo = false;
   1363     props.depthstencilAttachment_hasRbo = false;
   1364     mFboState.fboData[name] = props;
   1365 }
   1366 
   1367 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
   1368     for (size_t i = 0; i < n; i++) {
   1369         addFreshFramebuffer(framebuffers[i]);
   1370     }
   1371 }
   1372 
   1373 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
   1374     for (size_t i = 0; i < n; i++) {
   1375         if (framebuffers[i] != 0) { // Never remove the zero fb.
   1376             if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
   1377                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
   1378             }
   1379             if (framebuffers[i] == mFboState.boundReadFramebuffer) {
   1380                 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
   1381             }
   1382             mFboState.fboData.erase(framebuffers[i]);
   1383         }
   1384     }
   1385 }
   1386 
   1387 bool GLClientState::usedFramebufferName(GLuint name) const {
   1388     return mFboState.fboData.find(name) != mFboState.fboData.end();
   1389 }
   1390 
   1391 FboProps& GLClientState::boundFboProps(GLenum target) {
   1392     switch (target) {
   1393     case GL_DRAW_FRAMEBUFFER:
   1394         return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1395     case GL_READ_FRAMEBUFFER:
   1396         return mFboState.fboData[mFboState.boundReadFramebuffer];
   1397     case GL_FRAMEBUFFER:
   1398         return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1399     }
   1400     return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1401 }
   1402 
   1403 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
   1404     switch (target) {
   1405     case GL_DRAW_FRAMEBUFFER:
   1406         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1407     case GL_READ_FRAMEBUFFER:
   1408         return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
   1409     case GL_FRAMEBUFFER:
   1410         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1411     }
   1412     return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1413 }
   1414 
   1415 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
   1416     // If unused, add it.
   1417     if (!usedFramebufferName(name)) {
   1418         addFreshFramebuffer(name);
   1419     }
   1420     switch (target) {
   1421         case GL_DRAW_FRAMEBUFFER:
   1422             mFboState.boundDrawFramebuffer = name;
   1423             break;
   1424         case GL_READ_FRAMEBUFFER:
   1425             mFboState.boundReadFramebuffer = name;
   1426             break;
   1427         default: // case GL_FRAMEBUFFER:
   1428             mFboState.boundDrawFramebuffer = name;
   1429             mFboState.boundReadFramebuffer = name;
   1430             break;
   1431     }
   1432     boundFboProps(target).previouslyBound = true;
   1433 }
   1434 
   1435 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
   1436     switch (target) {
   1437         case GL_DRAW_FRAMEBUFFER:
   1438             mFboState.drawFboCheckStatus = status;
   1439             break;
   1440         case GL_READ_FRAMEBUFFER:
   1441             mFboState.readFboCheckStatus = status;
   1442             break;
   1443         case GL_FRAMEBUFFER:
   1444             mFboState.drawFboCheckStatus = status;
   1445             break;
   1446     }
   1447 }
   1448 
   1449 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
   1450     switch (target) {
   1451     case GL_DRAW_FRAMEBUFFER:
   1452         return mFboState.drawFboCheckStatus;
   1453     case GL_READ_FRAMEBUFFER:
   1454         return mFboState.readFboCheckStatus;
   1455     case GL_FRAMEBUFFER:
   1456         return mFboState.drawFboCheckStatus;
   1457     }
   1458     return mFboState.drawFboCheckStatus;
   1459 }
   1460 
   1461 GLuint GLClientState::boundFramebuffer(GLenum target) const {
   1462     return boundFboProps_const(target).name;
   1463 }
   1464 
   1465 // Texture objects for FBOs/////////////////////////////////////////////////////
   1466 
   1467 void GLClientState::attachTextureObject(
   1468         GLenum target,
   1469         GLenum attachment, GLuint texture) {
   1470 
   1471     int colorAttachmentIndex =
   1472         glUtilsColorAttachmentIndex(attachment);
   1473 
   1474     if (colorAttachmentIndex != -1) {
   1475         boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
   1476         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
   1477     }
   1478 
   1479     switch (attachment) {
   1480     case GL_DEPTH_ATTACHMENT:
   1481         boundFboProps(target).depthAttachment_texture = texture;
   1482         boundFboProps(target).depthAttachment_hasTexObj = true;
   1483         break;
   1484     case GL_STENCIL_ATTACHMENT:
   1485         boundFboProps(target).stencilAttachment_texture = texture;
   1486         boundFboProps(target).stencilAttachment_hasTexObj = true;
   1487         break;
   1488     case GL_DEPTH_STENCIL_ATTACHMENT:
   1489         boundFboProps(target).depthstencilAttachment_texture = texture;
   1490         boundFboProps(target).depthstencilAttachment_hasTexObj = true;
   1491         boundFboProps(target).stencilAttachment_texture = texture;
   1492         boundFboProps(target).stencilAttachment_hasTexObj = true;
   1493         boundFboProps(target).depthAttachment_texture = texture;
   1494         boundFboProps(target).depthAttachment_hasTexObj = true;
   1495         break;
   1496     }
   1497 }
   1498 
   1499 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
   1500     GLuint res = 0; // conservative
   1501 
   1502     int colorAttachmentIndex =
   1503         glUtilsColorAttachmentIndex(attachment);
   1504 
   1505     if (colorAttachmentIndex != -1) {
   1506         res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
   1507     }
   1508 
   1509     switch (attachment) {
   1510     case GL_DEPTH_ATTACHMENT:
   1511         res = boundFboProps_const(target).depthAttachment_texture;
   1512         break;
   1513     case GL_STENCIL_ATTACHMENT:
   1514         res = boundFboProps_const(target).stencilAttachment_texture;
   1515         break;
   1516     case GL_DEPTH_STENCIL_ATTACHMENT:
   1517         res = boundFboProps_const(target).depthstencilAttachment_texture;
   1518         break;
   1519     }
   1520     return res;
   1521 }
   1522 
   1523 // RBOs for FBOs////////////////////////////////////////////////////////////////
   1524 
   1525 void GLClientState::detachRbo(GLuint renderbuffer) {
   1526     for (int i = 0; i < m_max_color_attachments; i++) {
   1527         detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
   1528         detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
   1529     }
   1530 
   1531     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
   1532     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
   1533 
   1534     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
   1535     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
   1536 
   1537     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
   1538     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
   1539 }
   1540 
   1541 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
   1542     int colorAttachmentIndex =
   1543         glUtilsColorAttachmentIndex(attachment);
   1544 
   1545     if (colorAttachmentIndex != -1) {
   1546         if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
   1547             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
   1548             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
   1549             boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
   1550         }
   1551     }
   1552 
   1553     switch (attachment) {
   1554     case GL_DEPTH_ATTACHMENT:
   1555         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
   1556             boundFboProps(target).depthAttachment_hasRbo) {
   1557             boundFboProps(target).depthAttachment_rbo = 0;
   1558             boundFboProps(target).depthAttachment_hasRbo = false;
   1559         }
   1560         break;
   1561     case GL_STENCIL_ATTACHMENT:
   1562         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
   1563             boundFboProps(target).stencilAttachment_hasRbo) {
   1564             boundFboProps(target).stencilAttachment_rbo = 0;
   1565             boundFboProps(target).stencilAttachment_hasRbo = false;
   1566         }
   1567         break;
   1568     case GL_DEPTH_STENCIL_ATTACHMENT:
   1569         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
   1570             boundFboProps(target).depthAttachment_hasRbo) {
   1571             boundFboProps(target).depthAttachment_rbo = 0;
   1572             boundFboProps(target).depthAttachment_hasRbo = false;
   1573         }
   1574         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
   1575             boundFboProps(target).stencilAttachment_hasRbo) {
   1576             boundFboProps(target).stencilAttachment_rbo = 0;
   1577             boundFboProps(target).stencilAttachment_hasRbo = false;
   1578         }
   1579         if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
   1580             boundFboProps(target).depthstencilAttachment_hasRbo) {
   1581             boundFboProps(target).depthstencilAttachment_rbo = 0;
   1582             boundFboProps(target).depthstencilAttachment_hasRbo = false;
   1583         }
   1584         break;
   1585     }
   1586 }
   1587 
   1588 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
   1589 
   1590     int colorAttachmentIndex =
   1591         glUtilsColorAttachmentIndex(attachment);
   1592 
   1593     if (colorAttachmentIndex != -1) {
   1594         boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
   1595         boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
   1596     }
   1597 
   1598     switch (attachment) {
   1599     case GL_DEPTH_ATTACHMENT:
   1600         boundFboProps(target).depthAttachment_rbo = renderbuffer;
   1601         boundFboProps(target).depthAttachment_hasRbo = true;
   1602         break;
   1603     case GL_STENCIL_ATTACHMENT:
   1604         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
   1605         boundFboProps(target).stencilAttachment_hasRbo = true;
   1606         break;
   1607     case GL_DEPTH_STENCIL_ATTACHMENT:
   1608         boundFboProps(target).depthAttachment_rbo = renderbuffer;
   1609         boundFboProps(target).depthAttachment_hasRbo = true;
   1610         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
   1611         boundFboProps(target).stencilAttachment_hasRbo = true;
   1612         boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
   1613         boundFboProps(target).depthstencilAttachment_hasRbo = true;
   1614         break;
   1615     }
   1616 }
   1617 
   1618 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
   1619     GLuint res = 0; // conservative
   1620 
   1621     int colorAttachmentIndex =
   1622         glUtilsColorAttachmentIndex(attachment);
   1623 
   1624     if (colorAttachmentIndex != -1) {
   1625         res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
   1626     }
   1627 
   1628     switch (attachment) {
   1629     case GL_DEPTH_ATTACHMENT:
   1630         res = boundFboProps_const(target).depthAttachment_rbo;
   1631         break;
   1632     case GL_STENCIL_ATTACHMENT:
   1633         res = boundFboProps_const(target).stencilAttachment_rbo;
   1634         break;
   1635     case GL_DEPTH_STENCIL_ATTACHMENT:
   1636         res = boundFboProps_const(target).depthstencilAttachment_rbo;
   1637         break;
   1638     }
   1639     return res;
   1640 }
   1641 
   1642 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
   1643     bool res = true; // liberal
   1644 
   1645     int colorAttachmentIndex =
   1646         glUtilsColorAttachmentIndex(attachment);
   1647 
   1648     if (colorAttachmentIndex != -1) {
   1649         res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
   1650               boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
   1651     }
   1652 
   1653     switch (attachment) {
   1654     case GL_DEPTH_ATTACHMENT:
   1655         res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
   1656               (boundFboProps_const(target).depthAttachment_hasRbo);
   1657         break;
   1658     case GL_STENCIL_ATTACHMENT:
   1659         res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
   1660               (boundFboProps_const(target).stencilAttachment_hasRbo);
   1661         break;
   1662     case GL_DEPTH_STENCIL_ATTACHMENT:
   1663         res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
   1664               (boundFboProps_const(target).depthstencilAttachment_hasRbo);
   1665         break;
   1666     }
   1667     return res;
   1668 }
   1669 
   1670 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
   1671     const FboProps& props = boundFboProps_const(target);
   1672 
   1673     int colorAttachmentIndex =
   1674         glUtilsColorAttachmentIndex(attachment);
   1675 
   1676     if (colorAttachmentIndex != -1) {
   1677         if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
   1678             return props.colorAttachmenti_textures[colorAttachmentIndex];
   1679         } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
   1680             return props.colorAttachmenti_rbos[colorAttachmentIndex];
   1681         } else {
   1682             return 0;
   1683         }
   1684     }
   1685 
   1686     switch (attachment) {
   1687     case GL_DEPTH_ATTACHMENT:
   1688         if (props.depthAttachment_hasTexObj) {
   1689             return props.depthAttachment_texture;
   1690         } else if (props.depthAttachment_hasRbo) {
   1691             return props.depthAttachment_rbo;
   1692         } else {
   1693             return 0;
   1694         }
   1695         break;
   1696     case GL_STENCIL_ATTACHMENT:
   1697         if (props.stencilAttachment_hasTexObj) {
   1698             return props.stencilAttachment_texture;
   1699         } else if (props.stencilAttachment_hasRbo) {
   1700             return props.stencilAttachment_rbo;
   1701         } else {
   1702             return 0;
   1703         }
   1704     case GL_DEPTH_STENCIL_ATTACHMENT:
   1705         if (props.depthstencilAttachment_hasTexObj) {
   1706             return props.depthstencilAttachment_texture;
   1707         } else if (props.depthstencilAttachment_hasRbo) {
   1708             return props.depthstencilAttachment_rbo;
   1709         } else {
   1710             return 0;
   1711         }
   1712         break;
   1713     }
   1714     return 0;
   1715 }
   1716 
   1717 void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
   1718     m_transformFeedbackActiveUnpaused = activeUnpaused;
   1719 }
   1720 
   1721 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
   1722     return m_transformFeedbackActiveUnpaused;
   1723 }
   1724 
   1725 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
   1726     m_tex.textureRecs = sharedTexData;
   1727 }
   1728 
   1729 void GLClientState::fromMakeCurrent() {
   1730     if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
   1731         addFreshFramebuffer(0);
   1732     }
   1733     FboProps& default_fb_props = mFboState.fboData[0];
   1734     default_fb_props.colorAttachmenti_hasRbo[0] = true;
   1735     default_fb_props.depthAttachment_hasRbo = true;
   1736     default_fb_props.stencilAttachment_hasRbo = true;
   1737     default_fb_props.depthstencilAttachment_hasRbo = true;
   1738 }
   1739 
   1740 void GLClientState::initFromCaps(
   1741     int max_transform_feedback_separate_attribs,
   1742     int max_uniform_buffer_bindings,
   1743     int max_atomic_counter_buffer_bindings,
   1744     int max_shader_storage_buffer_bindings,
   1745     int max_vertex_attrib_bindings,
   1746     int max_color_attachments,
   1747     int max_draw_buffers) {
   1748 
   1749     m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
   1750 
   1751     if (m_glesMajorVersion >= 3) {
   1752         m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
   1753         m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
   1754         m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
   1755         m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
   1756 
   1757         if (m_max_transform_feedback_separate_attribs)
   1758             m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
   1759         if (m_max_uniform_buffer_bindings)
   1760             m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
   1761         if (m_max_atomic_counter_buffer_bindings)
   1762             m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
   1763         if (m_max_shader_storage_buffer_bindings)
   1764             m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
   1765 
   1766         BufferBinding buf0Binding;
   1767         buf0Binding.buffer = 0;
   1768         buf0Binding.offset = 0;
   1769         buf0Binding.size = 0;
   1770         buf0Binding.stride = 0;
   1771         buf0Binding.effectiveStride = 0;
   1772 
   1773         for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
   1774             m_indexedTransformFeedbackBuffers[i] = buf0Binding;
   1775         for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
   1776             m_indexedUniformBuffers[i] = buf0Binding;
   1777         for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
   1778             m_indexedAtomicCounterBuffers[i] = buf0Binding;
   1779         for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
   1780             m_indexedShaderStorageBuffers[i] = buf0Binding;
   1781     }
   1782 
   1783     m_max_color_attachments = max_color_attachments;
   1784     m_max_draw_buffers = max_draw_buffers;
   1785 
   1786     addFreshRenderbuffer(0);
   1787     addFreshFramebuffer(0);
   1788 
   1789     m_initialized = true;
   1790 }
   1791 
   1792 bool GLClientState::needsInitFromCaps() const {
   1793     return !m_initialized;
   1794 }
   1795