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