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::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
    668     UniformBlockInfoKey key;
    669     key.program = program;
    670     key.uniformBlockIndex = uniformBlockIndex;
    671 
    672     UniformBlockUniformInfo info;
    673     info.numActiveUniforms = (size_t)numActiveUniforms;
    674 
    675     m_uniformBlockInfoMap[key] = info;
    676 }
    677 
    678 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
    679     UniformBlockInfoKey key;
    680     key.program = program;
    681     key.uniformBlockIndex = uniformBlockIndex;
    682     UniformBlockInfoMap::const_iterator it =
    683         m_uniformBlockInfoMap.find(key);
    684     if (it == m_uniformBlockInfoMap.end()) return 0;
    685     return it->second.numActiveUniforms;
    686 }
    687 
    688 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
    689     m_programPipelines[program] = pipeline;
    690 }
    691 
    692 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
    693     return m_programPipelines.begin();
    694 }
    695 
    696 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
    697     return m_programPipelines.end();
    698 }
    699 
    700 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
    701 {
    702     GLuint unit = texture - GL_TEXTURE0;
    703     if (unit >= MAX_TEXTURE_UNITS) {
    704         return GL_INVALID_ENUM;
    705     }
    706     m_tex.activeUnit = &m_tex.unit[unit];
    707     return GL_NO_ERROR;
    708 }
    709 
    710 GLenum GLClientState::getActiveTextureUnit() const
    711 {
    712     return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
    713 }
    714 
    715 void GLClientState::enableTextureTarget(GLenum target)
    716 {
    717     switch (target) {
    718     case GL_TEXTURE_2D:
    719         m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
    720         break;
    721     case GL_TEXTURE_EXTERNAL_OES:
    722         m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
    723         break;
    724     }
    725 }
    726 
    727 void GLClientState::disableTextureTarget(GLenum target)
    728 {
    729     switch (target) {
    730     case GL_TEXTURE_2D:
    731         m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
    732         break;
    733     case GL_TEXTURE_EXTERNAL_OES:
    734         m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
    735         break;
    736     }
    737 }
    738 
    739 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
    740 {
    741     unsigned int enables = m_tex.activeUnit->enables;
    742     if (enables & (1u << TEXTURE_EXTERNAL)) {
    743         return GL_TEXTURE_EXTERNAL_OES;
    744     } else if (enables & (1u << TEXTURE_2D)) {
    745         return GL_TEXTURE_2D;
    746     } else {
    747         return allDisabled;
    748     }
    749 }
    750 
    751 int GLClientState::compareTexId(const void* pid, const void* prec)
    752 {
    753     const GLuint* id = (const GLuint*)pid;
    754     const TextureRec* rec = (const TextureRec*)prec;
    755     return (GLint)(*id) - (GLint)rec->id;
    756 }
    757 
    758 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
    759         GLboolean* firstUse)
    760 {
    761     GLboolean first = GL_FALSE;
    762 
    763     TextureRec* texrec = getTextureRec(texture);
    764     if (!texrec) {
    765         texrec = addTextureRec(texture, target);
    766     }
    767 
    768     if (texture && target != texrec->target &&
    769         (target != GL_TEXTURE_EXTERNAL_OES &&
    770          texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
    771         ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
    772     }
    773 
    774     switch (target) {
    775     case GL_TEXTURE_2D:
    776         m_tex.activeUnit->texture[TEXTURE_2D] = texture;
    777         break;
    778     case GL_TEXTURE_EXTERNAL_OES:
    779         m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
    780         break;
    781     case GL_TEXTURE_CUBE_MAP:
    782         m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
    783         break;
    784     case GL_TEXTURE_2D_ARRAY:
    785         m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
    786         break;
    787     case GL_TEXTURE_3D:
    788         m_tex.activeUnit->texture[TEXTURE_3D] = texture;
    789         break;
    790     case GL_TEXTURE_2D_MULTISAMPLE:
    791         m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
    792         break;
    793     }
    794 
    795     if (firstUse) {
    796         *firstUse = first;
    797     }
    798 
    799     return GL_NO_ERROR;
    800 }
    801 
    802 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
    803     GLuint texture = getBoundTexture(target);
    804     TextureRec* texrec = getTextureRec(texture);
    805     if (!texrec) return;
    806     texrec->boundEGLImage = true;
    807 }
    808 
    809 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
    810 {
    811     TextureRec* tex = new TextureRec;
    812     tex->id = id;
    813     tex->target = target;
    814     tex->format = -1;
    815     tex->multisamples = 0;
    816     tex->immutable = false;
    817     tex->boundEGLImage = false;
    818     tex->dims = new TextureDims;
    819 
    820     (*(m_tex.textureRecs))[id] = tex;
    821     return tex;
    822 }
    823 
    824 TextureRec* GLClientState::getTextureRec(GLuint id) const {
    825     SharedTextureDataMap::const_iterator it =
    826         m_tex.textureRecs->find(id);
    827     if (it == m_tex.textureRecs->end()) {
    828         return NULL;
    829     }
    830     return it->second;
    831 }
    832 
    833 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
    834     GLuint texture = getBoundTexture(target);
    835     TextureRec* texrec = getTextureRec(texture);
    836     if (!texrec) return;
    837     texrec->internalformat = internalformat;
    838 }
    839 
    840 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
    841     GLuint texture = getBoundTexture(target);
    842     TextureRec* texrec = getTextureRec(texture);
    843     if (!texrec) return;
    844     texrec->format = format;
    845 }
    846 
    847 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
    848     GLuint texture = getBoundTexture(target);
    849     TextureRec* texrec = getTextureRec(texture);
    850     if (!texrec) return;
    851     texrec->type = type;
    852 }
    853 
    854 void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
    855     GLuint texture = getBoundTexture(target);
    856     TextureRec* texrec = getTextureRec(texture);
    857     if (!texrec) {
    858         return;
    859     }
    860 
    861     if (level == -1) {
    862         GLsizei curr_width = width;
    863         GLsizei curr_height = height;
    864         GLsizei curr_depth = depth;
    865         GLsizei curr_level = 0;
    866 
    867         while (true) {
    868             texrec->dims->widths[curr_level] = curr_width;
    869             texrec->dims->heights[curr_level] = curr_height;
    870             texrec->dims->depths[curr_level] = curr_depth;
    871             if (curr_width >> 1 == 0 &&
    872                 curr_height >> 1 == 0 &&
    873                 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
    874                  true)) {
    875                 break;
    876             }
    877             curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
    878             curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
    879             if (target == GL_TEXTURE_3D) {
    880                 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
    881             }
    882             curr_level++;
    883         }
    884 
    885     } else {
    886         texrec->dims->widths[level] = width;
    887         texrec->dims->heights[level] = height;
    888         texrec->dims->depths[level] = depth;
    889     }
    890 }
    891 
    892 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
    893     GLuint texture = getBoundTexture(target);
    894     TextureRec* texrec = getTextureRec(texture);
    895     if (!texrec) return;
    896     texrec->multisamples = samples;
    897 }
    898 
    899 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
    900     GLuint texture = getBoundTexture(target);
    901     TextureRec* texrec = getTextureRec(texture);
    902     if (!texrec) return;
    903     texrec->immutable = true;
    904 }
    905 
    906 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
    907     GLuint texture = getBoundTexture(target);
    908     TextureRec* texrec = getTextureRec(texture);
    909     if (!texrec) return false;
    910     return texrec->immutable;
    911 }
    912 
    913 GLuint GLClientState::getBoundTexture(GLenum target) const
    914 {
    915     switch (target) {
    916     case GL_TEXTURE_2D:
    917         return m_tex.activeUnit->texture[TEXTURE_2D];
    918     case GL_TEXTURE_EXTERNAL_OES:
    919         return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
    920     case GL_TEXTURE_CUBE_MAP:
    921         return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
    922     case GL_TEXTURE_2D_ARRAY:
    923         return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
    924     case GL_TEXTURE_3D:
    925         return m_tex.activeUnit->texture[TEXTURE_3D];
    926     case GL_TEXTURE_2D_MULTISAMPLE:
    927         return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
    928     default:
    929         return 0;
    930     }
    931 }
    932 
    933 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    934 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
    935 
    936 static bool unreliableInternalFormat(GLenum internalformat) {
    937     switch (internalformat) {
    938     case GL_LUMINANCE:
    939         return true;
    940     default:
    941         return false;
    942     }
    943 }
    944 
    945 void GLClientState::writeCopyTexImageState
    946     (GLenum target, GLint level, GLenum internalformat) {
    947     if (unreliableInternalFormat(internalformat)) {
    948         CubeMapDef entry;
    949         entry.id = getBoundTexture(GL_TEXTURE_2D);
    950         entry.target = target;
    951         entry.level = level;
    952         entry.internalformat = internalformat;
    953         m_cubeMapDefs.insert(entry);
    954     }
    955 }
    956 
    957 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
    958     switch (target) {
    959     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    960         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
    961     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    962         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
    963     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    964         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
    965     default:
    966         return 0;
    967     }
    968 }
    969 
    970 GLenum GLClientState::copyTexImageNeededTarget
    971     (GLenum target, GLint level, GLenum internalformat) {
    972     if (unreliableInternalFormat(internalformat)) {
    973         GLenum positiveComponent =
    974             identifyPositiveCubeMapComponent(target);
    975         if (positiveComponent) {
    976             CubeMapDef query;
    977             query.id = getBoundTexture(GL_TEXTURE_2D);
    978             query.target = positiveComponent;
    979             query.level = level;
    980             query.internalformat = internalformat;
    981             if (m_cubeMapDefs.find(query) ==
    982                 m_cubeMapDefs.end()) {
    983                 return positiveComponent;
    984             }
    985         }
    986     }
    987     return 0;
    988 }
    989 
    990 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
    991     (GLenum target, GLint level, GLenum internalformat) {
    992     writeCopyTexImageState(target, level, internalformat);
    993     return copyTexImageNeededTarget(target, level, internalformat);
    994 }
    995 
    996 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
    997 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    998 
    999 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
   1000 {
   1001     // Updating the textures array could be made more efficient when deleting
   1002     // several textures:
   1003     // - compacting the array could be done in a single pass once the deleted
   1004     //   textures are marked, or
   1005     // - could swap deleted textures to the end and re-sort.
   1006     TextureRec* texrec;
   1007     for (const GLuint* texture = textures; texture != textures + n; texture++) {
   1008         texrec = getTextureRec(*texture);
   1009         if (texrec && texrec->dims) {
   1010             delete texrec->dims;
   1011         }
   1012         if (texrec) {
   1013             m_tex.textureRecs->erase(*texture);
   1014             delete texrec;
   1015             for (TextureUnit* unit = m_tex.unit;
   1016                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
   1017                  unit++)
   1018             {
   1019                 if (unit->texture[TEXTURE_2D] == *texture) {
   1020                     unit->texture[TEXTURE_2D] = 0;
   1021                 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
   1022                     unit->texture[TEXTURE_EXTERNAL] = 0;
   1023                 }
   1024             }
   1025         }
   1026     }
   1027 }
   1028 
   1029 // RBO//////////////////////////////////////////////////////////////////////////
   1030 
   1031 void GLClientState::addFreshRenderbuffer(GLuint name) {
   1032     // if underlying opengl says these are fresh names,
   1033     // but we are keeping a stale one, reset it.
   1034     RboProps props;
   1035     props.target = GL_RENDERBUFFER;
   1036     props.name = name;
   1037     props.format = GL_NONE;
   1038     props.multisamples = 0;
   1039     props.previouslyBound = false;
   1040 
   1041     if (usedRenderbufferName(name)) {
   1042         mRboState.rboData[getRboIndex(name)] = props;
   1043     } else {
   1044         mRboState.rboData.push_back(props);
   1045     }
   1046 }
   1047 
   1048 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
   1049     for (size_t i = 0; i < n; i++) {
   1050         addFreshRenderbuffer(renderbuffers[i]);
   1051     }
   1052 }
   1053 
   1054 size_t GLClientState::getRboIndex(GLuint name) const {
   1055     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1056         if (mRboState.rboData[i].name == name) {
   1057             return i;
   1058         }
   1059     }
   1060     return -1;
   1061 }
   1062 
   1063 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
   1064     size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
   1065 
   1066     std::vector<GLuint> to_remove;
   1067     for (size_t i = 0; i < n; i++) {
   1068         if (renderbuffers[i] != 0) { // Never remove the zero rb.
   1069             to_remove.push_back(getRboIndex(renderbuffers[i]));
   1070         }
   1071     }
   1072 
   1073     for (size_t i = 0; i < to_remove.size(); i++) {
   1074         mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
   1075         mRboState.rboData.pop_back();
   1076     }
   1077 
   1078     // If we just deleted the currently bound rb,
   1079     // bind the zero rb
   1080     if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
   1081         bindRenderbuffer(GL_RENDERBUFFER, 0);
   1082     }
   1083 }
   1084 
   1085 bool GLClientState::usedRenderbufferName(GLuint name) const {
   1086     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1087         if (mRboState.rboData[i].name == name) {
   1088             return true;
   1089         }
   1090     }
   1091     return false;
   1092 }
   1093 
   1094 void GLClientState::setBoundRenderbufferIndex() {
   1095     for (size_t i = 0; i < mRboState.rboData.size(); i++) {
   1096         if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
   1097             mRboState.boundRenderbufferIndex = i;
   1098             break;
   1099         }
   1100     }
   1101 }
   1102 
   1103 RboProps& GLClientState::boundRboProps() {
   1104     return mRboState.rboData[mRboState.boundRenderbufferIndex];
   1105 }
   1106 
   1107 const RboProps& GLClientState::boundRboProps_const() const {
   1108     return mRboState.rboData[mRboState.boundRenderbufferIndex];
   1109 }
   1110 
   1111 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
   1112     // If unused, add it.
   1113     if (!usedRenderbufferName(name)) {
   1114         addFreshRenderbuffer(name);
   1115     }
   1116     mRboState.boundRenderbuffer = name;
   1117     setBoundRenderbufferIndex();
   1118     boundRboProps().target = target;
   1119     boundRboProps().previouslyBound = true;
   1120 }
   1121 
   1122 GLuint GLClientState::boundRenderbuffer() const {
   1123     return boundRboProps_const().name;
   1124 }
   1125 
   1126 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
   1127     boundRboProps().format = format;
   1128 }
   1129 
   1130 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
   1131     boundRboProps().multisamples = samples;
   1132 }
   1133 
   1134 // FBO//////////////////////////////////////////////////////////////////////////
   1135 
   1136 // Format querying
   1137 
   1138 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
   1139     return mRboState.rboData[getRboIndex(rbo_name)].format;
   1140 }
   1141 
   1142 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
   1143     return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
   1144 }
   1145 
   1146 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
   1147     TextureRec* texrec = getTextureRec(tex_name);
   1148     if (!texrec) return -1;
   1149     return texrec->internalformat;
   1150 }
   1151 
   1152 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
   1153     TextureRec* texrec = getTextureRec(tex_name);
   1154     if (!texrec) {
   1155         return 0;
   1156     }
   1157     return texrec->dims->widths[level];
   1158 }
   1159 
   1160 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
   1161     TextureRec* texrec = getTextureRec(tex_name);
   1162     if (!texrec) return 0;
   1163     return texrec->dims->heights[level];
   1164 }
   1165 
   1166 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
   1167     TextureRec* texrec = getTextureRec(tex_name);
   1168     if (!texrec) return 0;
   1169     return texrec->dims->depths[level];
   1170 }
   1171 
   1172 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
   1173     TextureRec* texrec = getTextureRec(tex_name);
   1174     if (!texrec) return false;
   1175     return texrec->boundEGLImage;
   1176 }
   1177 
   1178 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
   1179     TextureRec* texrec = getTextureRec(tex_name);
   1180     if (!texrec) return -1;
   1181     return texrec->format;
   1182 }
   1183 
   1184 GLenum GLClientState::queryTexType(GLuint tex_name) const {
   1185     TextureRec* texrec = getTextureRec(tex_name);
   1186     if (!texrec) return -1;
   1187     return texrec->type;
   1188 }
   1189 
   1190 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
   1191     TextureRec* texrec = getTextureRec(tex_name);
   1192     if (!texrec) return 0;
   1193     return texrec->multisamples;
   1194 }
   1195 
   1196 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
   1197     TextureRec* texrec = getTextureRec(tex_name);
   1198     if (!texrec) return GL_NONE;
   1199     return texrec->target;
   1200 }
   1201 
   1202 void GLClientState::getBoundFramebufferFormat(
   1203         GLenum target,
   1204         GLenum attachment, FboFormatInfo* res_info) const {
   1205     const FboProps& props = boundFboProps_const(target);
   1206 
   1207     res_info->type = FBO_ATTACHMENT_NONE;
   1208     res_info->rb_format = GL_NONE;
   1209     res_info->rb_multisamples = 0;
   1210     res_info->tex_internalformat = -1;
   1211     res_info->tex_format = GL_NONE;
   1212     res_info->tex_type = GL_NONE;
   1213     res_info->tex_multisamples = 0;
   1214 
   1215     int colorAttachmentIndex =
   1216         glUtilsColorAttachmentIndex(attachment);
   1217 
   1218     if (colorAttachmentIndex != -1) {
   1219         if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
   1220             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1221             res_info->rb_format =
   1222                 queryRboFormat(
   1223                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1224             res_info->rb_multisamples =
   1225                 queryRboSamples(
   1226                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1227         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
   1228             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1229             res_info->tex_internalformat =
   1230                 queryTexInternalFormat(
   1231                         props.colorAttachmenti_textures[colorAttachmentIndex]);
   1232             res_info->tex_format =
   1233                 queryTexFormat(
   1234                         props.colorAttachmenti_textures[colorAttachmentIndex]);
   1235             res_info->tex_type =
   1236                 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1237             res_info->tex_multisamples =
   1238                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1239         } else {
   1240             res_info->type = FBO_ATTACHMENT_NONE;
   1241         }
   1242     }
   1243 
   1244     switch (attachment) {
   1245     case GL_DEPTH_ATTACHMENT:
   1246         if (props.depthAttachment_hasRbo) {
   1247             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1248             res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
   1249             res_info->rb_multisamples =
   1250                 queryRboSamples(
   1251                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1252         } else if (props.depthAttachment_hasTexObj) {
   1253             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1254             res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
   1255             res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
   1256             res_info->tex_type = queryTexType(props.depthAttachment_texture);
   1257             res_info->tex_multisamples =
   1258                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1259         } else {
   1260             res_info->type = FBO_ATTACHMENT_NONE;
   1261         }
   1262         break;
   1263     case GL_STENCIL_ATTACHMENT:
   1264         if (props.stencilAttachment_hasRbo) {
   1265             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1266             res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
   1267             res_info->rb_multisamples =
   1268                 queryRboSamples(
   1269                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1270         } else if (props.stencilAttachment_hasTexObj) {
   1271             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1272             res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
   1273             res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
   1274             res_info->tex_type = queryTexType(props.stencilAttachment_texture);
   1275             res_info->tex_multisamples =
   1276                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1277         } else {
   1278             res_info->type = FBO_ATTACHMENT_NONE;
   1279         }
   1280         break;
   1281     case GL_DEPTH_STENCIL_ATTACHMENT:
   1282         if (props.depthstencilAttachment_hasRbo) {
   1283             res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
   1284             res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
   1285             res_info->rb_multisamples =
   1286                 queryRboSamples(
   1287                         props.colorAttachmenti_rbos[colorAttachmentIndex]);
   1288         } else if (props.depthstencilAttachment_hasTexObj) {
   1289             res_info->type = FBO_ATTACHMENT_TEXTURE;
   1290             res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
   1291             res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
   1292             res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
   1293             res_info->tex_multisamples =
   1294                 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
   1295         } else {
   1296             res_info->type = FBO_ATTACHMENT_NONE;
   1297         }
   1298         break;
   1299     }
   1300 }
   1301 
   1302 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
   1303     FboFormatInfo info;
   1304     getBoundFramebufferFormat(target, attachment, &info);
   1305     return info.type;
   1306 }
   1307 
   1308 
   1309 int GLClientState::getMaxColorAttachments() const {
   1310     return m_max_color_attachments;
   1311 }
   1312 
   1313 int GLClientState::getMaxDrawBuffers() const {
   1314     return m_max_draw_buffers;
   1315 }
   1316 
   1317 void GLClientState::addFreshFramebuffer(GLuint name) {
   1318     FboProps props;
   1319     props.name = name;
   1320     props.previouslyBound = false;
   1321 
   1322     props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
   1323     props.depthAttachment_texture = 0;
   1324     props.stencilAttachment_texture = 0;
   1325     props.depthstencilAttachment_texture = 0;
   1326 
   1327     props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
   1328     props.depthAttachment_hasTexObj = false;
   1329     props.stencilAttachment_hasTexObj = false;
   1330     props.depthstencilAttachment_hasTexObj = false;
   1331 
   1332     props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
   1333     props.depthAttachment_rbo = 0;
   1334     props.stencilAttachment_rbo = 0;
   1335     props.depthstencilAttachment_rbo = 0;
   1336 
   1337     props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
   1338     props.depthAttachment_hasRbo = false;
   1339     props.stencilAttachment_hasRbo = false;
   1340     props.depthstencilAttachment_hasRbo = false;
   1341     mFboState.fboData[name] = props;
   1342 }
   1343 
   1344 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
   1345     for (size_t i = 0; i < n; i++) {
   1346         addFreshFramebuffer(framebuffers[i]);
   1347     }
   1348 }
   1349 
   1350 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
   1351     for (size_t i = 0; i < n; i++) {
   1352         if (framebuffers[i] != 0) { // Never remove the zero fb.
   1353             if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
   1354                 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
   1355             }
   1356             if (framebuffers[i] == mFboState.boundReadFramebuffer) {
   1357                 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
   1358             }
   1359             mFboState.fboData.erase(framebuffers[i]);
   1360         }
   1361     }
   1362 }
   1363 
   1364 bool GLClientState::usedFramebufferName(GLuint name) const {
   1365     return mFboState.fboData.find(name) != mFboState.fboData.end();
   1366 }
   1367 
   1368 FboProps& GLClientState::boundFboProps(GLenum target) {
   1369     switch (target) {
   1370     case GL_DRAW_FRAMEBUFFER:
   1371         return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1372     case GL_READ_FRAMEBUFFER:
   1373         return mFboState.fboData[mFboState.boundReadFramebuffer];
   1374     case GL_FRAMEBUFFER:
   1375         return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1376     }
   1377     return mFboState.fboData[mFboState.boundDrawFramebuffer];
   1378 }
   1379 
   1380 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
   1381     switch (target) {
   1382     case GL_DRAW_FRAMEBUFFER:
   1383         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1384     case GL_READ_FRAMEBUFFER:
   1385         return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
   1386     case GL_FRAMEBUFFER:
   1387         return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1388     }
   1389     return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
   1390 }
   1391 
   1392 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
   1393     // If unused, add it.
   1394     if (!usedFramebufferName(name)) {
   1395         addFreshFramebuffer(name);
   1396     }
   1397     switch (target) {
   1398         case GL_DRAW_FRAMEBUFFER:
   1399             mFboState.boundDrawFramebuffer = name;
   1400             break;
   1401         case GL_READ_FRAMEBUFFER:
   1402             mFboState.boundReadFramebuffer = name;
   1403             break;
   1404         default: // case GL_FRAMEBUFFER:
   1405             mFboState.boundDrawFramebuffer = name;
   1406             mFboState.boundReadFramebuffer = name;
   1407             break;
   1408     }
   1409     boundFboProps(target).previouslyBound = true;
   1410 }
   1411 
   1412 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
   1413     switch (target) {
   1414         case GL_DRAW_FRAMEBUFFER:
   1415             mFboState.drawFboCheckStatus = status;
   1416             break;
   1417         case GL_READ_FRAMEBUFFER:
   1418             mFboState.readFboCheckStatus = status;
   1419             break;
   1420         case GL_FRAMEBUFFER:
   1421             mFboState.drawFboCheckStatus = status;
   1422             break;
   1423     }
   1424 }
   1425 
   1426 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
   1427     switch (target) {
   1428     case GL_DRAW_FRAMEBUFFER:
   1429         return mFboState.drawFboCheckStatus;
   1430     case GL_READ_FRAMEBUFFER:
   1431         return mFboState.readFboCheckStatus;
   1432     case GL_FRAMEBUFFER:
   1433         return mFboState.drawFboCheckStatus;
   1434     }
   1435     return mFboState.drawFboCheckStatus;
   1436 }
   1437 
   1438 GLuint GLClientState::boundFramebuffer(GLenum target) const {
   1439     return boundFboProps_const(target).name;
   1440 }
   1441 
   1442 // Texture objects for FBOs/////////////////////////////////////////////////////
   1443 
   1444 void GLClientState::attachTextureObject(
   1445         GLenum target,
   1446         GLenum attachment, GLuint texture) {
   1447 
   1448     int colorAttachmentIndex =
   1449         glUtilsColorAttachmentIndex(attachment);
   1450 
   1451     if (colorAttachmentIndex != -1) {
   1452         boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
   1453         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
   1454     }
   1455 
   1456     switch (attachment) {
   1457     case GL_DEPTH_ATTACHMENT:
   1458         boundFboProps(target).depthAttachment_texture = texture;
   1459         boundFboProps(target).depthAttachment_hasTexObj = true;
   1460         break;
   1461     case GL_STENCIL_ATTACHMENT:
   1462         boundFboProps(target).stencilAttachment_texture = texture;
   1463         boundFboProps(target).stencilAttachment_hasTexObj = true;
   1464         break;
   1465     case GL_DEPTH_STENCIL_ATTACHMENT:
   1466         boundFboProps(target).depthstencilAttachment_texture = texture;
   1467         boundFboProps(target).depthstencilAttachment_hasTexObj = true;
   1468         boundFboProps(target).stencilAttachment_texture = texture;
   1469         boundFboProps(target).stencilAttachment_hasTexObj = true;
   1470         boundFboProps(target).depthAttachment_texture = texture;
   1471         boundFboProps(target).depthAttachment_hasTexObj = true;
   1472         break;
   1473     }
   1474 }
   1475 
   1476 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
   1477     GLuint res = 0; // conservative
   1478 
   1479     int colorAttachmentIndex =
   1480         glUtilsColorAttachmentIndex(attachment);
   1481 
   1482     if (colorAttachmentIndex != -1) {
   1483         res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
   1484     }
   1485 
   1486     switch (attachment) {
   1487     case GL_DEPTH_ATTACHMENT:
   1488         res = boundFboProps_const(target).depthAttachment_texture;
   1489         break;
   1490     case GL_STENCIL_ATTACHMENT:
   1491         res = boundFboProps_const(target).stencilAttachment_texture;
   1492         break;
   1493     case GL_DEPTH_STENCIL_ATTACHMENT:
   1494         res = boundFboProps_const(target).depthstencilAttachment_texture;
   1495         break;
   1496     }
   1497     return res;
   1498 }
   1499 
   1500 // RBOs for FBOs////////////////////////////////////////////////////////////////
   1501 
   1502 void GLClientState::detachRbo(GLuint renderbuffer) {
   1503     for (int i = 0; i < m_max_color_attachments; i++) {
   1504         detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
   1505         detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
   1506     }
   1507 
   1508     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
   1509     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
   1510 
   1511     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
   1512     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
   1513 
   1514     detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
   1515     detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
   1516 }
   1517 
   1518 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
   1519     int colorAttachmentIndex =
   1520         glUtilsColorAttachmentIndex(attachment);
   1521 
   1522     if (colorAttachmentIndex != -1) {
   1523         if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
   1524             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
   1525             boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
   1526             boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
   1527         }
   1528     }
   1529 
   1530     switch (attachment) {
   1531     case GL_DEPTH_ATTACHMENT:
   1532         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
   1533             boundFboProps(target).depthAttachment_hasRbo) {
   1534             boundFboProps(target).depthAttachment_rbo = 0;
   1535             boundFboProps(target).depthAttachment_hasRbo = false;
   1536         }
   1537         break;
   1538     case GL_STENCIL_ATTACHMENT:
   1539         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
   1540             boundFboProps(target).stencilAttachment_hasRbo) {
   1541             boundFboProps(target).stencilAttachment_rbo = 0;
   1542             boundFboProps(target).stencilAttachment_hasRbo = false;
   1543         }
   1544         break;
   1545     case GL_DEPTH_STENCIL_ATTACHMENT:
   1546         if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
   1547             boundFboProps(target).depthAttachment_hasRbo) {
   1548             boundFboProps(target).depthAttachment_rbo = 0;
   1549             boundFboProps(target).depthAttachment_hasRbo = false;
   1550         }
   1551         if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
   1552             boundFboProps(target).stencilAttachment_hasRbo) {
   1553             boundFboProps(target).stencilAttachment_rbo = 0;
   1554             boundFboProps(target).stencilAttachment_hasRbo = false;
   1555         }
   1556         if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
   1557             boundFboProps(target).depthstencilAttachment_hasRbo) {
   1558             boundFboProps(target).depthstencilAttachment_rbo = 0;
   1559             boundFboProps(target).depthstencilAttachment_hasRbo = false;
   1560         }
   1561         break;
   1562     }
   1563 }
   1564 
   1565 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
   1566 
   1567     int colorAttachmentIndex =
   1568         glUtilsColorAttachmentIndex(attachment);
   1569 
   1570     if (colorAttachmentIndex != -1) {
   1571         boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
   1572         boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
   1573     }
   1574 
   1575     switch (attachment) {
   1576     case GL_DEPTH_ATTACHMENT:
   1577         boundFboProps(target).depthAttachment_rbo = renderbuffer;
   1578         boundFboProps(target).depthAttachment_hasRbo = true;
   1579         break;
   1580     case GL_STENCIL_ATTACHMENT:
   1581         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
   1582         boundFboProps(target).stencilAttachment_hasRbo = true;
   1583         break;
   1584     case GL_DEPTH_STENCIL_ATTACHMENT:
   1585         boundFboProps(target).depthAttachment_rbo = renderbuffer;
   1586         boundFboProps(target).depthAttachment_hasRbo = true;
   1587         boundFboProps(target).stencilAttachment_rbo = renderbuffer;
   1588         boundFboProps(target).stencilAttachment_hasRbo = true;
   1589         boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
   1590         boundFboProps(target).depthstencilAttachment_hasRbo = true;
   1591         break;
   1592     }
   1593 }
   1594 
   1595 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
   1596     GLuint res = 0; // conservative
   1597 
   1598     int colorAttachmentIndex =
   1599         glUtilsColorAttachmentIndex(attachment);
   1600 
   1601     if (colorAttachmentIndex != -1) {
   1602         res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
   1603     }
   1604 
   1605     switch (attachment) {
   1606     case GL_DEPTH_ATTACHMENT:
   1607         res = boundFboProps_const(target).depthAttachment_rbo;
   1608         break;
   1609     case GL_STENCIL_ATTACHMENT:
   1610         res = boundFboProps_const(target).stencilAttachment_rbo;
   1611         break;
   1612     case GL_DEPTH_STENCIL_ATTACHMENT:
   1613         res = boundFboProps_const(target).depthstencilAttachment_rbo;
   1614         break;
   1615     }
   1616     return res;
   1617 }
   1618 
   1619 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
   1620     bool res = true; // liberal
   1621 
   1622     int colorAttachmentIndex =
   1623         glUtilsColorAttachmentIndex(attachment);
   1624 
   1625     if (colorAttachmentIndex != -1) {
   1626         res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
   1627               boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
   1628     }
   1629 
   1630     switch (attachment) {
   1631     case GL_DEPTH_ATTACHMENT:
   1632         res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
   1633               (boundFboProps_const(target).depthAttachment_hasRbo);
   1634         break;
   1635     case GL_STENCIL_ATTACHMENT:
   1636         res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
   1637               (boundFboProps_const(target).stencilAttachment_hasRbo);
   1638         break;
   1639     case GL_DEPTH_STENCIL_ATTACHMENT:
   1640         res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
   1641               (boundFboProps_const(target).depthstencilAttachment_hasRbo);
   1642         break;
   1643     }
   1644     return res;
   1645 }
   1646 
   1647 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
   1648     const FboProps& props = boundFboProps_const(target);
   1649 
   1650     int colorAttachmentIndex =
   1651         glUtilsColorAttachmentIndex(attachment);
   1652 
   1653     if (colorAttachmentIndex != -1) {
   1654         if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
   1655             return props.colorAttachmenti_textures[colorAttachmentIndex];
   1656         } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
   1657             return props.colorAttachmenti_rbos[colorAttachmentIndex];
   1658         } else {
   1659             return 0;
   1660         }
   1661     }
   1662 
   1663     switch (attachment) {
   1664     case GL_DEPTH_ATTACHMENT:
   1665         if (props.depthAttachment_hasTexObj) {
   1666             return props.depthAttachment_texture;
   1667         } else if (props.depthAttachment_hasRbo) {
   1668             return props.depthAttachment_rbo;
   1669         } else {
   1670             return 0;
   1671         }
   1672         break;
   1673     case GL_STENCIL_ATTACHMENT:
   1674         if (props.stencilAttachment_hasTexObj) {
   1675             return props.stencilAttachment_texture;
   1676         } else if (props.stencilAttachment_hasRbo) {
   1677             return props.stencilAttachment_rbo;
   1678         } else {
   1679             return 0;
   1680         }
   1681     case GL_DEPTH_STENCIL_ATTACHMENT:
   1682         if (props.depthstencilAttachment_hasTexObj) {
   1683             return props.depthstencilAttachment_texture;
   1684         } else if (props.depthstencilAttachment_hasRbo) {
   1685             return props.depthstencilAttachment_rbo;
   1686         } else {
   1687             return 0;
   1688         }
   1689         break;
   1690     }
   1691     return 0;
   1692 }
   1693 
   1694 void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
   1695     m_transformFeedbackActiveUnpaused = activeUnpaused;
   1696 }
   1697 
   1698 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
   1699     return m_transformFeedbackActiveUnpaused;
   1700 }
   1701 
   1702 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
   1703     m_tex.textureRecs = sharedTexData;
   1704 }
   1705 
   1706 void GLClientState::fromMakeCurrent() {
   1707     if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
   1708         addFreshFramebuffer(0);
   1709     }
   1710     FboProps& default_fb_props = mFboState.fboData[0];
   1711     default_fb_props.colorAttachmenti_hasRbo[0] = true;
   1712     default_fb_props.depthAttachment_hasRbo = true;
   1713     default_fb_props.stencilAttachment_hasRbo = true;
   1714     default_fb_props.depthstencilAttachment_hasRbo = true;
   1715 }
   1716 
   1717 void GLClientState::initFromCaps(
   1718     int max_transform_feedback_separate_attribs,
   1719     int max_uniform_buffer_bindings,
   1720     int max_atomic_counter_buffer_bindings,
   1721     int max_shader_storage_buffer_bindings,
   1722     int max_vertex_attrib_bindings,
   1723     int max_color_attachments,
   1724     int max_draw_buffers) {
   1725 
   1726     m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
   1727 
   1728     if (m_glesMajorVersion >= 3) {
   1729         m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
   1730         m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
   1731         m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
   1732         m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
   1733 
   1734         if (m_max_transform_feedback_separate_attribs)
   1735             m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
   1736         if (m_max_uniform_buffer_bindings)
   1737             m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
   1738         if (m_max_atomic_counter_buffer_bindings)
   1739             m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
   1740         if (m_max_shader_storage_buffer_bindings)
   1741             m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
   1742 
   1743         BufferBinding buf0Binding;
   1744         buf0Binding.buffer = 0;
   1745         buf0Binding.offset = 0;
   1746         buf0Binding.size = 0;
   1747         buf0Binding.stride = 0;
   1748         buf0Binding.effectiveStride = 0;
   1749 
   1750         for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
   1751             m_indexedTransformFeedbackBuffers[i] = buf0Binding;
   1752         for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
   1753             m_indexedUniformBuffers[i] = buf0Binding;
   1754         for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
   1755             m_indexedAtomicCounterBuffers[i] = buf0Binding;
   1756         for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
   1757             m_indexedShaderStorageBuffers[i] = buf0Binding;
   1758     }
   1759 
   1760     m_max_color_attachments = max_color_attachments;
   1761     m_max_draw_buffers = max_draw_buffers;
   1762 
   1763     addFreshRenderbuffer(0);
   1764     addFreshFramebuffer(0);
   1765 
   1766     m_initialized = true;
   1767 }
   1768 
   1769 bool GLClientState::needsInitFromCaps() const {
   1770     return !m_initialized;
   1771 }
   1772