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 #ifndef _GL_CLIENT_STATE_H_
     17 #define _GL_CLIENT_STATE_H_
     18 
     19 #define GL_API
     20 #ifndef ANDROID
     21 #define GL_APIENTRY
     22 #define GL_APIENTRYP
     23 #endif
     24 
     25 #include <GLES/gl.h>
     26 #include <GLES/glext.h>
     27 #include <GLES2/gl2.h>
     28 #include <GLES2/gl2ext.h>
     29 
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 #include "ErrorLog.h"
     33 #include "codec_defs.h"
     34 
     35 #include <vector>
     36 #include <set>
     37 
     38 // Tracking framebuffer objects:
     39 // which framebuffer is bound,
     40 // and which texture names
     41 // are currently bound to which attachment points.
     42 struct FboProps {
     43     GLenum target;
     44     GLuint name;
     45     bool previouslyBound;
     46     GLuint colorAttachment0_texture;
     47     GLuint depthAttachment_texture;
     48     GLuint stencilAttachment_texture;
     49 
     50     bool colorAttachment0_hasTexObj;
     51     bool depthAttachment_hasTexObj;
     52     bool stencilAttachment_hasTexObj;
     53 
     54     GLuint colorAttachment0_rbo;
     55     GLuint depthAttachment_rbo;
     56     GLuint stencilAttachment_rbo;
     57 
     58     bool colorAttachment0_hasRbo;
     59     bool depthAttachment_hasRbo;
     60     bool stencilAttachment_hasRbo;
     61 };
     62 
     63 // Same for Rbo's
     64 struct RboProps {
     65     GLenum target;
     66     GLuint name;
     67     GLenum format;
     68     bool previouslyBound;
     69 };
     70 
     71 // Enum for describing whether a framebuffer attachment
     72 // is a texture or renderbuffer.
     73 enum FboAttachmentType {
     74     FBO_ATTACHMENT_RENDERBUFFER = 0,
     75     FBO_ATTACHMENT_TEXTURE = 1,
     76     FBO_ATTACHMENT_NONE = 2
     77 };
     78 
     79 // Tracking FBO format
     80 struct FboFormatInfo {
     81     FboAttachmentType type;
     82     GLenum rb_format;
     83     GLint tex_internalformat;
     84     GLenum tex_format;
     85     GLenum tex_type;
     86 };
     87 
     88 class GLClientState {
     89 public:
     90     typedef enum {
     91         VERTEX_LOCATION = 0,
     92         NORMAL_LOCATION = 1,
     93         COLOR_LOCATION = 2,
     94         POINTSIZE_LOCATION = 3,
     95         TEXCOORD0_LOCATION = 4,
     96         TEXCOORD1_LOCATION = 5,
     97         TEXCOORD2_LOCATION = 6,
     98         TEXCOORD3_LOCATION = 7,
     99         TEXCOORD4_LOCATION = 8,
    100         TEXCOORD5_LOCATION = 9,
    101         TEXCOORD6_LOCATION = 10,
    102         TEXCOORD7_LOCATION = 11,
    103         MATRIXINDEX_LOCATION = 12,
    104         WEIGHT_LOCATION = 13,
    105         LAST_LOCATION = 14
    106     } StateLocation;
    107 
    108     typedef struct {
    109         GLint enabled;
    110         GLint size;
    111         GLenum type;
    112         GLsizei stride;
    113         void *data;
    114         GLuint bufferObject;
    115         GLenum glConst;
    116         unsigned int elementSize;
    117         bool enableDirty;  // true if any enable state has changed since last draw
    118         bool normalized;
    119     } VertexAttribState;
    120 
    121     typedef struct {
    122         int unpack_alignment;
    123         int pack_alignment;
    124     } PixelStoreState;
    125 
    126     enum {
    127         MAX_TEXTURE_UNITS = 32,
    128     };
    129 
    130 public:
    131     GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES);
    132     ~GLClientState();
    133     int nLocations() { return m_nLocations; }
    134     const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
    135     int setPixelStore(GLenum param, GLint value);
    136     GLuint currentArrayVbo() { return m_currentArrayVbo; }
    137     GLuint currentIndexVbo() { return m_currentIndexVbo; }
    138     void enable(int location, int state);
    139     void setState(int  location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data);
    140     void setBufferObject(int location, GLuint id);
    141     const VertexAttribState  *getState(int location);
    142     const VertexAttribState  *getStateAndEnableDirty(int location, bool *enableChanged);
    143     int getLocation(GLenum loc);
    144     void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
    145     int getActiveTexture() const { return m_activeTexture; }
    146     void setMaxVertexAttribs(int val) {
    147         m_maxVertexAttribs = val;
    148         m_maxVertexAttribsDirty = false;
    149     }
    150 
    151     void unBindBuffer(GLuint id)
    152     {
    153         if (m_currentArrayVbo == id) m_currentArrayVbo = 0;
    154         else if (m_currentIndexVbo == id) m_currentIndexVbo = 0;
    155     }
    156 
    157     int bindBuffer(GLenum target, GLuint id)
    158     {
    159         int err = 0;
    160         switch(target) {
    161         case GL_ARRAY_BUFFER:
    162             m_currentArrayVbo = id;
    163             break;
    164         case GL_ELEMENT_ARRAY_BUFFER:
    165             m_currentIndexVbo = id;
    166             break;
    167         default:
    168             err = -1;
    169         }
    170         return err;
    171     }
    172 
    173     int getBuffer(GLenum target)
    174     {
    175       int ret=0;
    176       switch (target) {
    177       case GL_ARRAY_BUFFER:
    178           ret = m_currentArrayVbo;
    179           break;
    180       case GL_ELEMENT_ARRAY_BUFFER:
    181           ret = m_currentIndexVbo;
    182           break;
    183       default:
    184           ret = -1;
    185       }
    186       return ret;
    187     }
    188     size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) const;
    189 
    190     void setCurrentProgram(GLint program) { m_currentProgram = program; }
    191     GLint currentProgram() const { return m_currentProgram; }
    192 
    193     /* OES_EGL_image_external
    194      *
    195      * These functions manipulate GL state which interacts with the
    196      * OES_EGL_image_external extension, to support client-side emulation on
    197      * top of host implementations that don't have it.
    198      *
    199      * Most of these calls should only be used with TEXTURE_2D or
    200      * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension
    201      * targets should bypass this. An exception is bindTexture(), which should
    202      * see all glBindTexture() calls for any target.
    203      */
    204 
    205     // glActiveTexture(GL_TEXTURE0 + i)
    206     // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported.
    207     GLenum setActiveTextureUnit(GLenum texture);
    208     GLenum getActiveTextureUnit() const;
    209 
    210     // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES))
    211     void enableTextureTarget(GLenum target);
    212 
    213     // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES))
    214     void disableTextureTarget(GLenum target);
    215 
    216     // Implements the target priority logic:
    217     // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else
    218     // * Return GL_TEXTURE_2D if enabled, else
    219     // * Return the allDisabled value.
    220     // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code
    221     // simpler; for other cases passing a recognizable enum like GL_ZERO or
    222     // GL_INVALID_ENUM is appropriate.
    223     GLenum getPriorityEnabledTarget(GLenum allDisabled) const;
    224 
    225     // glBindTexture(GL_TEXTURE_*, ...)
    226     // Set the target binding of the active texture unit to texture. Returns
    227     // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has
    228     // previously been bound to a different target. If firstUse is not NULL,
    229     // it is set to indicate whether this is the first use of the texture.
    230     // For accurate error detection, bindTexture should be called for *all*
    231     // targets, not just 2D and EXTERNAL_OES.
    232     GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
    233 
    234     // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
    235     GLuint getBoundTexture(GLenum target) const;
    236 
    237     // For AMD GPUs, it is easy for the emulator to segfault
    238     // (esp. in dEQP) when a cube map is defined using glCopyTexImage2D
    239     // and uses GL_LUMINANCE as internal format.
    240     // In particular, the segfault happens when negative components of
    241     // cube maps are defined before positive ones,
    242     // This procedure checks internal state to see if we have defined
    243     // the positive component of a cube map already. If not, it returns
    244     // which positive component needs to be defined first.
    245     // If there is no need for the extra definition, 0 is returned.
    246     GLenum copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target, GLint level,
    247                                                      GLenum internalformat);
    248 
    249     // Tracks the format of the currently bound texture.
    250     // This is to pass dEQP tests for fbo completeness.
    251     void setBoundTextureInternalFormat(GLenum target, GLint format);
    252     void setBoundTextureFormat(GLenum target, GLenum format);
    253     void setBoundTextureType(GLenum target, GLenum type);
    254 
    255     // glDeleteTextures(...)
    256     // Remove references to the to-be-deleted textures.
    257     void deleteTextures(GLsizei n, const GLuint* textures);
    258 
    259     // Render buffer objects
    260     void addRenderbuffers(GLsizei n, GLuint* renderbuffers);
    261     void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers);
    262     bool usedRenderbufferName(GLuint name) const;
    263     void bindRenderbuffer(GLenum target, GLuint name);
    264     GLuint boundRenderbuffer() const;
    265     void setBoundRenderbufferFormat(GLenum format);
    266 
    267     // Frame buffer objects
    268     void addFramebuffers(GLsizei n, GLuint* framebuffers);
    269     void removeFramebuffers(GLsizei n, const GLuint* framebuffers);
    270     bool usedFramebufferName(GLuint name) const;
    271     void bindFramebuffer(GLenum target, GLuint name);
    272     void setCheckFramebufferStatus(GLenum status);
    273     GLenum getCheckFramebufferStatus() const;
    274     GLuint boundFramebuffer() const;
    275 
    276     // Texture object -> FBO
    277     void attachTextureObject(GLenum attachment, GLuint texture);
    278     GLuint getFboAttachmentTextureId(GLenum attachment) const;
    279 
    280     // RBO -> FBO
    281     void attachRbo(GLenum attachment, GLuint renderbuffer);
    282     GLuint getFboAttachmentRboId(GLenum attachment) const;
    283 
    284     // FBO attachments in general
    285     bool attachmentHasObject(GLenum attachment) const;
    286 
    287     // set eglsurface property on default framebuffer
    288     // if coming from eglMakeCurrent
    289     void fromMakeCurrent();
    290 
    291     // Queries the format backing the current framebuffer.
    292     // Type differs depending on whether the attachment
    293     // is a texture or renderbuffer.
    294     void getBoundFramebufferFormat(
    295             GLenum attachment, FboFormatInfo* res_info) const;
    296 
    297 private:
    298     PixelStoreState m_pixelStore;
    299     VertexAttribState *m_states;
    300     int m_maxVertexAttribs;
    301     bool m_maxVertexAttribsDirty;
    302     int m_nLocations;
    303     GLuint m_currentArrayVbo;
    304     GLuint m_currentIndexVbo;
    305     int m_activeTexture;
    306     GLint m_currentProgram;
    307 
    308     bool validLocation(int location) { return (location >= 0 && location < m_nLocations); }
    309 
    310     enum TextureTarget {
    311         TEXTURE_2D = 0,
    312         TEXTURE_EXTERNAL = 1,
    313         TEXTURE_TARGET_COUNT
    314     };
    315     struct TextureUnit {
    316         unsigned int enables;
    317         GLuint texture[TEXTURE_TARGET_COUNT];
    318     };
    319     struct TextureRec {
    320         GLuint id;
    321         GLenum target;
    322         GLint internalformat;
    323         GLenum format;
    324         GLenum type;
    325     };
    326     struct TextureState {
    327         TextureUnit unit[MAX_TEXTURE_UNITS];
    328         TextureUnit* activeUnit;
    329         TextureRec* textures;
    330         GLuint numTextures;
    331         GLuint allocTextures;
    332     };
    333     TextureState m_tex;
    334 
    335     // State tracking of cube map definitions.
    336     // Currently used only for driver workarounds
    337     // when using GL_LUMINANCE and defining cube maps with
    338     // glCopyTexImage2D.
    339     struct CubeMapDef {
    340         GLuint id;
    341         GLenum target;
    342         GLint level;
    343         GLenum internalformat;
    344     };
    345     struct CubeMapDefCompare {
    346         bool operator() (const CubeMapDef& a,
    347                          const CubeMapDef& b) const {
    348             if (a.id != b.id) return a.id < b.id;
    349             if (a.target != b.target) return a.target < b.target;
    350             if (a.level != b.level) return a.level < b.level;
    351             if (a.internalformat != b.internalformat)
    352                 return a.internalformat < b.internalformat;
    353             return false;
    354         }
    355     };
    356     std::set<CubeMapDef, CubeMapDefCompare> m_cubeMapDefs;
    357     void writeCopyTexImageState(GLenum target, GLint level,
    358                                 GLenum internalformat);
    359     GLenum copyTexImageNeededTarget(GLenum target, GLint level,
    360                                     GLenum internalformat);
    361 
    362     struct RboState {
    363         GLuint boundRenderbuffer;
    364         size_t boundRenderbufferIndex;
    365         std::vector<RboProps> rboData;
    366     };
    367     RboState mRboState;
    368     void addFreshRenderbuffer(GLuint name);
    369     void setBoundRenderbufferIndex();
    370     size_t getRboIndex(GLuint name) const;
    371     RboProps& boundRboProps();
    372     const RboProps& boundRboProps_const() const;
    373 
    374     struct FboState {
    375         GLuint boundFramebuffer;
    376         size_t boundFramebufferIndex;
    377         std::vector<FboProps> fboData;
    378         GLenum fboCheckStatus;
    379     };
    380     FboState mFboState;
    381     void addFreshFramebuffer(GLuint name);
    382     void setBoundFramebufferIndex();
    383     size_t getFboIndex(GLuint name) const;
    384     FboProps& boundFboProps();
    385     const FboProps& boundFboProps_const() const;
    386 
    387     // Querying framebuffer format
    388     GLenum queryRboFormat(GLuint name) const;
    389     GLint queryTexInternalFormat(GLuint name) const;
    390     GLenum queryTexFormat(GLuint name) const;
    391     GLenum queryTexType(GLuint name) const;
    392 
    393     static int compareTexId(const void* pid, const void* prec);
    394     TextureRec* addTextureRec(GLuint id, GLenum target);
    395 
    396 public:
    397     void getClientStatePointer(GLenum pname, GLvoid** params);
    398 
    399     template <class T>
    400     int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
    401     {
    402         bool handled = true;
    403         const VertexAttribState *vertexAttrib = getState(index);
    404         if (vertexAttrib == NULL) {
    405             ERR("getVeterxAttriParameter for non existant index %d\n", index);
    406             // set gl error;
    407             return handled;
    408         }
    409 
    410         switch(param) {
    411         case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
    412             *ptr = (T)(vertexAttrib->bufferObject);
    413             break;
    414         case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
    415             *ptr = (T)(vertexAttrib->enabled);
    416             break;
    417         case GL_VERTEX_ATTRIB_ARRAY_SIZE:
    418             *ptr = (T)(vertexAttrib->size);
    419             break;
    420         case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
    421             *ptr = (T)(vertexAttrib->stride);
    422             break;
    423         case GL_VERTEX_ATTRIB_ARRAY_TYPE:
    424             *ptr = (T)(vertexAttrib->type);
    425             break;
    426         case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
    427             *ptr = (T)(vertexAttrib->normalized);
    428             break;
    429         case GL_CURRENT_VERTEX_ATTRIB:
    430             handled = false;
    431             break;
    432         default:
    433             handled = false;
    434             ERR("unknown vertex-attrib parameter param %d\n", param);
    435         }
    436         return handled;
    437     }
    438 
    439     template <class T>
    440     bool getClientStateParameter(GLenum param, T* ptr)
    441     {
    442         bool isClientStateParam = false;
    443         switch (param) {
    444         case GL_CLIENT_ACTIVE_TEXTURE: {
    445             GLint tex = getActiveTexture() + GL_TEXTURE0;
    446             *ptr = tex;
    447             isClientStateParam = true;
    448             break;
    449             }
    450         case GL_VERTEX_ARRAY_SIZE: {
    451             const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
    452             *ptr = state->size;
    453             isClientStateParam = true;
    454             break;
    455             }
    456         case GL_VERTEX_ARRAY_TYPE: {
    457             const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
    458             *ptr = state->type;
    459             isClientStateParam = true;
    460             break;
    461             }
    462         case GL_VERTEX_ARRAY_STRIDE: {
    463             const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
    464             *ptr = state->stride;
    465             isClientStateParam = true;
    466             break;
    467             }
    468         case GL_COLOR_ARRAY_SIZE: {
    469             const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
    470             *ptr = state->size;
    471             isClientStateParam = true;
    472             break;
    473             }
    474         case GL_COLOR_ARRAY_TYPE: {
    475             const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
    476             *ptr = state->type;
    477             isClientStateParam = true;
    478             break;
    479             }
    480         case GL_COLOR_ARRAY_STRIDE: {
    481             const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
    482             *ptr = state->stride;
    483             isClientStateParam = true;
    484             break;
    485             }
    486         case GL_NORMAL_ARRAY_TYPE: {
    487             const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
    488             *ptr = state->type;
    489             isClientStateParam = true;
    490             break;
    491             }
    492         case GL_NORMAL_ARRAY_STRIDE: {
    493             const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
    494             *ptr = state->stride;
    495             isClientStateParam = true;
    496             break;
    497             }
    498         case GL_TEXTURE_COORD_ARRAY_SIZE: {
    499             const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    500             *ptr = state->size;
    501             isClientStateParam = true;
    502             break;
    503             }
    504         case GL_TEXTURE_COORD_ARRAY_TYPE: {
    505             const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    506             *ptr = state->type;
    507             isClientStateParam = true;
    508             break;
    509             }
    510         case GL_TEXTURE_COORD_ARRAY_STRIDE: {
    511             const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    512             *ptr = state->stride;
    513             isClientStateParam = true;
    514             break;
    515             }
    516         case GL_POINT_SIZE_ARRAY_TYPE_OES: {
    517             const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
    518             *ptr = state->type;
    519             isClientStateParam = true;
    520             break;
    521             }
    522         case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
    523             const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
    524             *ptr = state->stride;
    525             isClientStateParam = true;
    526             break;
    527             }
    528         case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
    529             const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
    530             *ptr = state->size;
    531             isClientStateParam = true;
    532             break;
    533             }
    534         case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
    535             const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
    536             *ptr = state->type;
    537             isClientStateParam = true;
    538             break;
    539             }
    540         case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
    541             const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
    542             *ptr = state->stride;
    543             isClientStateParam = true;
    544             break;
    545             }
    546         case GL_WEIGHT_ARRAY_SIZE_OES: {
    547             const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
    548             *ptr = state->size;
    549             isClientStateParam = true;
    550             break;
    551             }
    552         case GL_WEIGHT_ARRAY_TYPE_OES: {
    553             const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
    554             *ptr = state->type;
    555             isClientStateParam = true;
    556             break;
    557             }
    558         case GL_WEIGHT_ARRAY_STRIDE_OES: {
    559             const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
    560             *ptr = state->stride;
    561             isClientStateParam = true;
    562             break;
    563             }
    564         case GL_VERTEX_ARRAY_BUFFER_BINDING: {
    565             const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
    566             *ptr = state->bufferObject;
    567             isClientStateParam = true;
    568             break;
    569             }
    570         case GL_NORMAL_ARRAY_BUFFER_BINDING: {
    571             const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
    572             *ptr = state->bufferObject;
    573             isClientStateParam = true;
    574             break;
    575             }
    576         case GL_COLOR_ARRAY_BUFFER_BINDING: {
    577             const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
    578             *ptr = state->bufferObject;
    579             isClientStateParam = true;
    580             break;
    581             }
    582         case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
    583             const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
    584             *ptr = state->bufferObject;
    585             isClientStateParam = true;
    586             break;
    587             }
    588         case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
    589             const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
    590             *ptr = state->bufferObject;
    591             isClientStateParam = true;
    592             break;
    593             }
    594         case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
    595             const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
    596             *ptr = state->bufferObject;
    597             isClientStateParam = true;
    598             break;
    599             }
    600         case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
    601             const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
    602             *ptr = state->bufferObject;
    603             isClientStateParam = true;
    604             break;
    605             }
    606         case GL_ARRAY_BUFFER_BINDING: {
    607             int buffer = getBuffer(GL_ARRAY_BUFFER);
    608             *ptr = buffer;
    609             isClientStateParam = true;
    610             break;
    611             }
    612         case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
    613             int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
    614             *ptr = buffer;
    615             isClientStateParam = true;
    616             break;
    617             }
    618         case GL_MAX_VERTEX_ATTRIBS: {
    619             if (m_maxVertexAttribsDirty) {
    620                 isClientStateParam = false;
    621             } else {
    622                 *ptr = m_maxVertexAttribs;
    623                 isClientStateParam = true;
    624             }
    625             break;
    626             }
    627         }
    628         return isClientStateParam;
    629     }
    630 
    631 };
    632 #endif
    633