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 "TextureSharedData.h"
     26 
     27 #include <GLES/gl.h>
     28 #include <GLES/glext.h>
     29 #include <GLES2/gl2.h>
     30 #include <GLES2/gl2ext.h>
     31 
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include "ErrorLog.h"
     35 #include "codec_defs.h"
     36 
     37 #include <vector>
     38 #include <map>
     39 #include <set>
     40 
     41 // Tracking framebuffer objects:
     42 // which framebuffer is bound,
     43 // and which texture names
     44 // are currently bound to which attachment points.
     45 struct FboProps {
     46     GLuint name;
     47     bool previouslyBound;
     48     std::vector<GLuint> colorAttachmenti_textures;
     49     GLuint depthAttachment_texture;
     50     GLuint stencilAttachment_texture;
     51     GLuint depthstencilAttachment_texture;
     52 
     53     std::vector<bool> colorAttachmenti_hasTex;
     54     bool depthAttachment_hasTexObj;
     55     bool stencilAttachment_hasTexObj;
     56     bool depthstencilAttachment_hasTexObj;
     57 
     58     std::vector<GLuint> colorAttachmenti_rbos;
     59     GLuint depthAttachment_rbo;
     60     GLuint stencilAttachment_rbo;
     61     GLuint depthstencilAttachment_rbo;
     62 
     63     std::vector<bool> colorAttachmenti_hasRbo;
     64     bool depthAttachment_hasRbo;
     65     bool stencilAttachment_hasRbo;
     66     bool depthstencilAttachment_hasRbo;
     67 };
     68 
     69 // Same for Rbo's
     70 struct RboProps {
     71     GLenum target;
     72     GLuint name;
     73     GLenum format;
     74     GLsizei multisamples;
     75     bool previouslyBound;
     76 };
     77 
     78 // Enum for describing whether a framebuffer attachment
     79 // is a texture or renderbuffer.
     80 enum FboAttachmentType {
     81     FBO_ATTACHMENT_RENDERBUFFER = 0,
     82     FBO_ATTACHMENT_TEXTURE = 1,
     83     FBO_ATTACHMENT_NONE = 2
     84 };
     85 
     86 // Tracking FBO format
     87 struct FboFormatInfo {
     88     FboAttachmentType type;
     89     GLenum rb_format;
     90     GLsizei rb_multisamples;
     91 
     92     GLint tex_internalformat;
     93     GLenum tex_format;
     94     GLenum tex_type;
     95     GLsizei tex_multisamples;
     96 };
     97 
     98 class GLClientState {
     99 public:
    100     typedef enum {
    101         VERTEX_LOCATION = 0,
    102         NORMAL_LOCATION = 1,
    103         COLOR_LOCATION = 2,
    104         POINTSIZE_LOCATION = 3,
    105         TEXCOORD0_LOCATION = 4,
    106         TEXCOORD1_LOCATION = 5,
    107         TEXCOORD2_LOCATION = 6,
    108         TEXCOORD3_LOCATION = 7,
    109         TEXCOORD4_LOCATION = 8,
    110         TEXCOORD5_LOCATION = 9,
    111         TEXCOORD6_LOCATION = 10,
    112         TEXCOORD7_LOCATION = 11,
    113         MATRIXINDEX_LOCATION = 12,
    114         WEIGHT_LOCATION = 13,
    115         LAST_LOCATION = 14
    116     } StateLocation;
    117 
    118     typedef struct {
    119         GLint enabled;
    120         GLint size;
    121         GLenum type;
    122         GLsizei stride;
    123         void *data;
    124         GLuint reloffset;
    125         GLuint bufferObject;
    126         GLenum glConst;
    127         unsigned int elementSize;
    128         bool enableDirty;  // true if any enable state has changed since last draw
    129         bool normalized;
    130         GLuint divisor;
    131         bool isInt;
    132         int bindingindex;
    133     } VertexAttribState;
    134 
    135     struct BufferBinding {
    136         GLintptr offset;
    137         GLintptr stride;
    138         GLintptr effectiveStride;
    139         GLsizeiptr size;
    140         GLuint buffer;
    141         GLuint divisor;
    142     };
    143 
    144     typedef std::vector<VertexAttribState> VertexAttribStateVector;
    145     typedef std::vector<BufferBinding> VertexAttribBindingVector;
    146 
    147     struct VAOState {
    148         VAOState(GLuint ibo, int nLoc, int nBindings) :
    149             element_array_buffer_binding(ibo),
    150             attribState(nLoc),
    151             bindingState(nBindings) { }
    152         VertexAttribStateVector attribState;
    153         VertexAttribBindingVector bindingState;
    154         GLuint element_array_buffer_binding;
    155     };
    156 
    157     typedef std::map<GLuint, VAOState> VAOStateMap;
    158     struct VAOStateRef {
    159         VAOStateRef() { }
    160         VAOStateRef(
    161                 VAOStateMap::iterator iter) : it(iter) { }
    162         VertexAttribState& operator[](size_t k) { return it->second.attribState[k]; }
    163         BufferBinding& bufferBinding(size_t k) { return it->second.bindingState[k]; }
    164         VertexAttribBindingVector& bufferBindings() { return it->second.bindingState; }
    165         const VertexAttribBindingVector& bufferBindings_const() const { return it->second.bindingState; }
    166         GLuint vaoId() const { return it->first; }
    167         GLuint& iboId() { return it->second.element_array_buffer_binding; }
    168         VAOStateMap::iterator it;
    169     };
    170 
    171     typedef struct {
    172         int unpack_alignment;
    173 
    174         int unpack_row_length;
    175         int unpack_image_height;
    176         int unpack_skip_pixels;
    177         int unpack_skip_rows;
    178         int unpack_skip_images;
    179 
    180         int pack_alignment;
    181 
    182         int pack_row_length;
    183         int pack_skip_pixels;
    184         int pack_skip_rows;
    185     } PixelStoreState;
    186 
    187     enum {
    188         MAX_TEXTURE_UNITS = 256,
    189     };
    190 
    191 public:
    192     GLClientState();
    193     GLClientState(int majorVersion, int minorVersion);
    194     ~GLClientState();
    195     int nLocations() { return m_nLocations; }
    196     const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
    197     int setPixelStore(GLenum param, GLint value);
    198     GLuint currentVertexArrayObject() const { return m_currVaoState.vaoId(); }
    199     const VertexAttribBindingVector& currentVertexBufferBindings() const {
    200         return m_currVaoState.bufferBindings_const();
    201     }
    202 
    203     GLuint currentArrayVbo() { return m_arrayBuffer; }
    204     GLuint currentIndexVbo() { return m_currVaoState.iboId(); }
    205     void enable(int location, int state);
    206     // Vertex array objects and vertex attributes
    207     void addVertexArrayObjects(GLsizei n, GLuint* arrays);
    208     void removeVertexArrayObjects(GLsizei n, const GLuint* arrays);
    209     void addVertexArrayObject(GLuint name);
    210     void removeVertexArrayObject(GLuint name);
    211     void setVertexArrayObject(GLuint vao);
    212     bool isVertexArrayObject(GLuint vao) const;
    213     void setVertexAttribState(int  location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt = false);
    214     void setVertexBindingDivisor(int bindingindex, GLuint divisor);
    215     const BufferBinding& getCurrAttributeBindingInfo(int attribindex);
    216     void setVertexAttribBinding(int attribindex, int bindingindex);
    217     void setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt = false);
    218     const VertexAttribState& getState(int location);
    219     const VertexAttribState& getStateAndEnableDirty(int location, bool *enableChanged);
    220     int getLocation(GLenum loc);
    221     void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
    222     int getActiveTexture() const { return m_activeTexture; }
    223     void setMaxVertexAttribs(int val) {
    224         m_maxVertexAttribs = val;
    225         m_maxVertexAttribsDirty = false;
    226     }
    227 
    228     void addBuffer(GLuint id);
    229     void removeBuffer(GLuint id);
    230     bool bufferIdExists(GLuint id) const;
    231     void unBindBuffer(GLuint id);
    232 
    233     int bindBuffer(GLenum target, GLuint id);
    234     void bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride);
    235     int getMaxIndexedBufferBindings(GLenum target) const;
    236 
    237     int getBuffer(GLenum target);
    238 
    239     size_t pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
    240     size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
    241     size_t clearBufferNumElts(GLenum buffer) const;
    242 
    243     void setCurrentProgram(GLint program) { m_currentProgram = program; }
    244     void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
    245     GLint currentProgram() const { return m_currentProgram; }
    246     GLint currentShaderProgram() const { return m_currentShaderProgram; }
    247 
    248     struct UniformBlockInfoKey {
    249         GLuint program;
    250         GLuint uniformBlockIndex;
    251     };
    252     struct UniformBlockInfoKeyCompare {
    253         bool operator() (const UniformBlockInfoKey& a,
    254                          const UniformBlockInfoKey& b) const {
    255             if (a.program != b.program) return a.program < b.program;
    256             if (a.uniformBlockIndex != b.uniformBlockIndex) return a.uniformBlockIndex < b.uniformBlockIndex;
    257             return false;
    258         }
    259     };
    260     struct UniformBlockUniformInfo {
    261         size_t numActiveUniforms;
    262     };
    263 
    264     typedef std::map<UniformBlockInfoKey, UniformBlockUniformInfo, UniformBlockInfoKeyCompare> UniformBlockInfoMap;
    265     UniformBlockInfoMap m_uniformBlockInfoMap;
    266 
    267     void setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms);
    268     size_t numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const;
    269 
    270     typedef std::map<GLuint, GLuint> ProgramPipelineMap;
    271     typedef ProgramPipelineMap::iterator ProgramPipelineIterator;
    272     void associateProgramWithPipeline(GLuint program, GLuint pipeline);
    273     ProgramPipelineIterator programPipelineBegin();
    274     ProgramPipelineIterator programPipelineEnd();
    275 
    276     /* OES_EGL_image_external
    277      *
    278      * These functions manipulate GL state which interacts with the
    279      * OES_EGL_image_external extension, to support client-side emulation on
    280      * top of host implementations that don't have it.
    281      *
    282      * Most of these calls should only be used with TEXTURE_2D or
    283      * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension
    284      * targets should bypass this. An exception is bindTexture(), which should
    285      * see all glBindTexture() calls for any target.
    286      */
    287 
    288     // glActiveTexture(GL_TEXTURE0 + i)
    289     // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported.
    290     GLenum setActiveTextureUnit(GLenum texture);
    291     GLenum getActiveTextureUnit() const;
    292 
    293     // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES))
    294     void enableTextureTarget(GLenum target);
    295 
    296     // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES))
    297     void disableTextureTarget(GLenum target);
    298 
    299     // Implements the target priority logic:
    300     // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else
    301     // * Return GL_TEXTURE_2D if enabled, else
    302     // * Return the allDisabled value.
    303     // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code
    304     // simpler; for other cases passing a recognizable enum like GL_ZERO or
    305     // GL_INVALID_ENUM is appropriate.
    306     GLenum getPriorityEnabledTarget(GLenum allDisabled) const;
    307 
    308     // glBindTexture(GL_TEXTURE_*, ...)
    309     // Set the target binding of the active texture unit to texture. Returns
    310     // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has
    311     // previously been bound to a different target. If firstUse is not NULL,
    312     // it is set to indicate whether this is the first use of the texture.
    313     // For accurate error detection, bindTexture should be called for *all*
    314     // targets, not just 2D and EXTERNAL_OES.
    315     GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
    316     void setBoundEGLImage(GLenum target, GLeglImageOES image);
    317 
    318     // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
    319     GLuint getBoundTexture(GLenum target) const;
    320     // Other publicly-visible texture queries
    321     GLenum queryTexLastBoundTarget(GLuint name) const;
    322     GLenum queryTexFormat(GLuint name) const;
    323     GLint queryTexInternalFormat(GLuint name) const;
    324     GLsizei queryTexWidth(GLsizei level, GLuint name) const;
    325     GLsizei queryTexHeight(GLsizei level, GLuint name) const;
    326     GLsizei queryTexDepth(GLsizei level, GLuint name) const;
    327     bool queryTexEGLImageBacked(GLuint name) const;
    328 
    329     // For AMD GPUs, it is easy for the emulator to segfault
    330     // (esp. in dEQP) when a cube map is defined using glCopyTexImage2D
    331     // and uses GL_LUMINANCE as internal format.
    332     // In particular, the segfault happens when negative components of
    333     // cube maps are defined before positive ones,
    334     // This procedure checks internal state to see if we have defined
    335     // the positive component of a cube map already. If not, it returns
    336     // which positive component needs to be defined first.
    337     // If there is no need for the extra definition, 0 is returned.
    338     GLenum copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target, GLint level,
    339                                                      GLenum internalformat);
    340 
    341     // Tracks the format of the currently bound texture.
    342     // This is to pass dEQP tests for fbo completeness.
    343     void setBoundTextureInternalFormat(GLenum target, GLint format);
    344     void setBoundTextureFormat(GLenum target, GLenum format);
    345     void setBoundTextureType(GLenum target, GLenum type);
    346     void setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth);
    347     void setBoundTextureSamples(GLenum target, GLsizei samples);
    348 
    349     // glTexStorage2D disallows any change in texture format after it is set for a particular texture.
    350     void setBoundTextureImmutableFormat(GLenum target);
    351     bool isBoundTextureImmutableFormat(GLenum target) const;
    352 
    353     // glDeleteTextures(...)
    354     // Remove references to the to-be-deleted textures.
    355     void deleteTextures(GLsizei n, const GLuint* textures);
    356 
    357     // Render buffer objects
    358     void addRenderbuffers(GLsizei n, GLuint* renderbuffers);
    359     void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers);
    360     bool usedRenderbufferName(GLuint name) const;
    361     void bindRenderbuffer(GLenum target, GLuint name);
    362     GLuint boundRenderbuffer() const;
    363     void setBoundRenderbufferFormat(GLenum format);
    364     void setBoundRenderbufferSamples(GLsizei samples);
    365 
    366     // Frame buffer objects
    367     void addFramebuffers(GLsizei n, GLuint* framebuffers);
    368     void removeFramebuffers(GLsizei n, const GLuint* framebuffers);
    369     bool usedFramebufferName(GLuint name) const;
    370     void bindFramebuffer(GLenum target, GLuint name);
    371     void setCheckFramebufferStatus(GLenum target, GLenum status);
    372     GLenum getCheckFramebufferStatus(GLenum target) const;
    373     GLuint boundFramebuffer(GLenum target) const;
    374 
    375     // Texture object -> FBO
    376     void attachTextureObject(GLenum target, GLenum attachment, GLuint texture);
    377     GLuint getFboAttachmentTextureId(GLenum target, GLenum attachment) const;
    378 
    379     // RBO -> FBO
    380     void detachRbo(GLuint renderbuffer);
    381     void detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer);
    382     void attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer);
    383     GLuint getFboAttachmentRboId(GLenum target, GLenum attachment) const;
    384 
    385     // FBO attachments in general
    386     bool attachmentHasObject(GLenum target, GLenum attachment) const;
    387     GLuint objectOfAttachment(GLenum target, GLenum attachment) const;
    388 
    389     // Transform feedback state
    390     void setTransformFeedbackActiveUnpaused(bool activeUnpaused);
    391     bool getTransformFeedbackActiveUnpaused() const;
    392 
    393     void setTextureData(SharedTextureDataMap* sharedTexData);
    394     // set eglsurface property on default framebuffer
    395     // if coming from eglMakeCurrent
    396     void fromMakeCurrent();
    397     // set indexed buffer state.
    398     // We need to query the underlying OpenGL to get
    399     // accurate values for indexed buffers
    400     // and # render targets.
    401     void initFromCaps(
    402         int max_transform_feedback_separate_attribs,
    403         int max_uniform_buffer_bindings,
    404         int max_atomic_counter_buffer_bindings,
    405         int max_shader_storage_buffer_bindings,
    406         int max_vertex_attrib_bindings,
    407         int max_color_attachments,
    408         int max_draw_buffers);
    409     bool needsInitFromCaps() const;
    410 
    411     // Queries the format backing the current framebuffer.
    412     // Type differs depending on whether the attachment
    413     // is a texture or renderbuffer.
    414     void getBoundFramebufferFormat(
    415             GLenum target,
    416             GLenum attachment,
    417             FboFormatInfo* res_info) const;
    418     FboAttachmentType getBoundFramebufferAttachmentType(
    419             GLenum target,
    420             GLenum attachment) const;
    421     int getMaxColorAttachments() const;
    422     int getMaxDrawBuffers() const;
    423 private:
    424     void init();
    425     bool m_initialized;
    426     PixelStoreState m_pixelStore;
    427 
    428     std::set<GLuint> mBufferIds;
    429 
    430     // GL_ARRAY_BUFFER_BINDING is separate from VAO state
    431     GLuint m_arrayBuffer;
    432     VAOStateMap m_vaoMap;
    433     VAOStateRef m_currVaoState;
    434 
    435     // Other buffer id's, other targets
    436     GLuint m_copyReadBuffer;
    437     GLuint m_copyWriteBuffer;
    438 
    439     GLuint m_pixelPackBuffer;
    440     GLuint m_pixelUnpackBuffer;
    441 
    442     GLuint m_transformFeedbackBuffer;
    443     GLuint m_uniformBuffer;
    444 
    445     GLuint m_atomicCounterBuffer;
    446     GLuint m_dispatchIndirectBuffer;
    447     GLuint m_drawIndirectBuffer;
    448     GLuint m_shaderStorageBuffer;
    449 
    450     bool m_transformFeedbackActiveUnpaused;
    451 
    452     int m_max_transform_feedback_separate_attribs;
    453     int m_max_uniform_buffer_bindings;
    454     int m_max_atomic_counter_buffer_bindings;
    455     int m_max_shader_storage_buffer_bindings;
    456     int m_max_vertex_attrib_bindings;
    457     std::vector<BufferBinding> m_indexedTransformFeedbackBuffers;
    458     std::vector<BufferBinding> m_indexedUniformBuffers;
    459     std::vector<BufferBinding> m_indexedAtomicCounterBuffers;
    460     std::vector<BufferBinding> m_indexedShaderStorageBuffers;
    461 
    462     int m_glesMajorVersion;
    463     int m_glesMinorVersion;
    464     int m_maxVertexAttribs;
    465     bool m_maxVertexAttribsDirty;
    466     int m_nLocations;
    467     int m_activeTexture;
    468     GLint m_currentProgram;
    469     GLint m_currentShaderProgram;
    470     ProgramPipelineMap m_programPipelines;
    471 
    472     enum TextureTarget {
    473         TEXTURE_2D = 0,
    474         TEXTURE_EXTERNAL = 1,
    475         TEXTURE_CUBE_MAP = 2,
    476         TEXTURE_2D_ARRAY = 3,
    477         TEXTURE_3D = 4,
    478         TEXTURE_2D_MULTISAMPLE = 5,
    479         TEXTURE_TARGET_COUNT
    480     };
    481     struct TextureUnit {
    482         unsigned int enables;
    483         GLuint texture[TEXTURE_TARGET_COUNT];
    484     };
    485     struct TextureState {
    486         TextureUnit unit[MAX_TEXTURE_UNITS];
    487         TextureUnit* activeUnit;
    488         // Initialized from shared group.
    489         SharedTextureDataMap* textureRecs;
    490     };
    491     TextureState m_tex;
    492 
    493     // State tracking of cube map definitions.
    494     // Currently used only for driver workarounds
    495     // when using GL_LUMINANCE and defining cube maps with
    496     // glCopyTexImage2D.
    497     struct CubeMapDef {
    498         GLuint id;
    499         GLenum target;
    500         GLint level;
    501         GLenum internalformat;
    502     };
    503     struct CubeMapDefCompare {
    504         bool operator() (const CubeMapDef& a,
    505                          const CubeMapDef& b) const {
    506             if (a.id != b.id) return a.id < b.id;
    507             if (a.target != b.target) return a.target < b.target;
    508             if (a.level != b.level) return a.level < b.level;
    509             if (a.internalformat != b.internalformat)
    510                 return a.internalformat < b.internalformat;
    511             return false;
    512         }
    513     };
    514     std::set<CubeMapDef, CubeMapDefCompare> m_cubeMapDefs;
    515     void writeCopyTexImageState(GLenum target, GLint level,
    516                                 GLenum internalformat);
    517     GLenum copyTexImageNeededTarget(GLenum target, GLint level,
    518                                     GLenum internalformat);
    519 
    520     int m_max_color_attachments;
    521     int m_max_draw_buffers;
    522     struct RboState {
    523         GLuint boundRenderbuffer;
    524         size_t boundRenderbufferIndex;
    525         std::vector<RboProps> rboData;
    526     };
    527     RboState mRboState;
    528     void addFreshRenderbuffer(GLuint name);
    529     void setBoundRenderbufferIndex();
    530     size_t getRboIndex(GLuint name) const;
    531     RboProps& boundRboProps();
    532     const RboProps& boundRboProps_const() const;
    533 
    534     struct FboState {
    535         GLuint boundDrawFramebuffer;
    536         GLuint boundReadFramebuffer;
    537         size_t boundFramebufferIndex;
    538         std::map<GLuint, FboProps> fboData;
    539         GLenum drawFboCheckStatus;
    540         GLenum readFboCheckStatus;
    541     };
    542     FboState mFboState;
    543     void addFreshFramebuffer(GLuint name);
    544     FboProps& boundFboProps(GLenum target);
    545     const FboProps& boundFboProps_const(GLenum target) const;
    546 
    547     // Querying framebuffer format
    548     GLenum queryRboFormat(GLuint name) const;
    549     GLsizei queryRboSamples(GLuint name) const;
    550     GLenum queryTexType(GLuint name) const;
    551     GLsizei queryTexSamples(GLuint name) const;
    552 
    553     static int compareTexId(const void* pid, const void* prec);
    554     TextureRec* addTextureRec(GLuint id, GLenum target);
    555     TextureRec* getTextureRec(GLuint id) const;
    556 
    557 public:
    558     void getClientStatePointer(GLenum pname, GLvoid** params);
    559 
    560     template <class T>
    561     int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
    562     {
    563         bool handled = true;
    564         const VertexAttribState& vertexAttrib = getState(index);
    565         const BufferBinding& vertexAttribBufferBinding =
    566             m_currVaoState.bufferBindings_const()[vertexAttrib.bindingindex];
    567 
    568         switch(param) {
    569 #define GL_VERTEX_ATTRIB_BINDING 0x82D4
    570         case GL_VERTEX_ATTRIB_BINDING:
    571             *ptr = (T)vertexAttrib.bindingindex;
    572             break;
    573 #define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
    574         case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
    575             *ptr = (T)vertexAttrib.reloffset;
    576             break;
    577         case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
    578             *ptr = (T)(vertexAttribBufferBinding.buffer);
    579             break;
    580         case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
    581             *ptr = (T)(vertexAttrib.enabled);
    582             break;
    583 #define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
    584         case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
    585             *ptr = (T)(vertexAttrib.isInt);
    586             break;
    587         case GL_VERTEX_ATTRIB_ARRAY_SIZE:
    588             *ptr = (T)(vertexAttrib.size);
    589             break;
    590         case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
    591             *ptr = (T)(vertexAttribBufferBinding.stride);
    592             break;
    593         case GL_VERTEX_ATTRIB_ARRAY_TYPE:
    594             *ptr = (T)(vertexAttrib.type);
    595             break;
    596         case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
    597             *ptr = (T)(vertexAttrib.normalized);
    598             break;
    599         case GL_CURRENT_VERTEX_ATTRIB:
    600             handled = false;
    601             break;
    602         default:
    603             handled = false;
    604             ERR("unknown vertex-attrib parameter param %d\n", param);
    605         }
    606         return handled;
    607     }
    608 
    609     template <class T>
    610     bool getClientStateParameter(GLenum param, T* out)
    611     {
    612         bool isClientStateParam = false;
    613         switch (param) {
    614         case GL_CLIENT_ACTIVE_TEXTURE: {
    615             GLint tex = getActiveTexture() + GL_TEXTURE0;
    616             *out = tex;
    617             isClientStateParam = true;
    618             break;
    619             }
    620         case GL_VERTEX_ARRAY_SIZE: {
    621             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
    622             *out = state.size;
    623             isClientStateParam = true;
    624             break;
    625             }
    626         case GL_VERTEX_ARRAY_TYPE: {
    627             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
    628             *out = state.type;
    629             isClientStateParam = true;
    630             break;
    631             }
    632         case GL_VERTEX_ARRAY_STRIDE: {
    633             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
    634             *out = state.stride;
    635             isClientStateParam = true;
    636             break;
    637             }
    638         case GL_COLOR_ARRAY_SIZE: {
    639             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
    640             *out = state.size;
    641             isClientStateParam = true;
    642             break;
    643             }
    644         case GL_COLOR_ARRAY_TYPE: {
    645             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
    646             *out = state.type;
    647             isClientStateParam = true;
    648             break;
    649             }
    650         case GL_COLOR_ARRAY_STRIDE: {
    651             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
    652             *out = state.stride;
    653             isClientStateParam = true;
    654             break;
    655             }
    656         case GL_NORMAL_ARRAY_TYPE: {
    657             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
    658             *out = state.type;
    659             isClientStateParam = true;
    660             break;
    661             }
    662         case GL_NORMAL_ARRAY_STRIDE: {
    663             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
    664             *out = state.stride;
    665             isClientStateParam = true;
    666             break;
    667             }
    668         case GL_TEXTURE_COORD_ARRAY_SIZE: {
    669             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    670             *out = state.size;
    671             isClientStateParam = true;
    672             break;
    673             }
    674         case GL_TEXTURE_COORD_ARRAY_TYPE: {
    675             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    676             *out = state.type;
    677             isClientStateParam = true;
    678             break;
    679             }
    680         case GL_TEXTURE_COORD_ARRAY_STRIDE: {
    681             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
    682             *out = state.stride;
    683             isClientStateParam = true;
    684             break;
    685             }
    686         case GL_POINT_SIZE_ARRAY_TYPE_OES: {
    687             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
    688             *out = state.type;
    689             isClientStateParam = true;
    690             break;
    691             }
    692         case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
    693             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
    694             *out = state.stride;
    695             isClientStateParam = true;
    696             break;
    697             }
    698         case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
    699             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
    700             *out = state.size;
    701             isClientStateParam = true;
    702             break;
    703             }
    704         case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
    705             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
    706             *out = state.type;
    707             isClientStateParam = true;
    708             break;
    709             }
    710         case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
    711             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
    712             *out = state.stride;
    713             isClientStateParam = true;
    714             break;
    715             }
    716         case GL_WEIGHT_ARRAY_SIZE_OES: {
    717             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
    718             *out = state.size;
    719             isClientStateParam = true;
    720             break;
    721             }
    722         case GL_WEIGHT_ARRAY_TYPE_OES: {
    723             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
    724             *out = state.type;
    725             isClientStateParam = true;
    726             break;
    727             }
    728         case GL_WEIGHT_ARRAY_STRIDE_OES: {
    729             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
    730             *out = state.stride;
    731             isClientStateParam = true;
    732             break;
    733             }
    734         case GL_VERTEX_ARRAY_BUFFER_BINDING: {
    735             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
    736             *out = state.bufferObject;
    737             isClientStateParam = true;
    738             break;
    739             }
    740         case GL_NORMAL_ARRAY_BUFFER_BINDING: {
    741             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
    742             *out = state.bufferObject;
    743             isClientStateParam = true;
    744             break;
    745             }
    746         case GL_COLOR_ARRAY_BUFFER_BINDING: {
    747             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
    748             *out = state.bufferObject;
    749             isClientStateParam = true;
    750             break;
    751             }
    752         case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
    753             const GLClientState::VertexAttribState& state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
    754             *out = state.bufferObject;
    755             isClientStateParam = true;
    756             break;
    757             }
    758         case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
    759             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
    760             *out = state.bufferObject;
    761             isClientStateParam = true;
    762             break;
    763             }
    764         case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
    765             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
    766             *out = state.bufferObject;
    767             isClientStateParam = true;
    768             break;
    769             }
    770         case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
    771             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
    772             *out = state.bufferObject;
    773             isClientStateParam = true;
    774             break;
    775             }
    776         case GL_ARRAY_BUFFER_BINDING: {
    777             int buffer = getBuffer(GL_ARRAY_BUFFER);
    778             *out = buffer;
    779             isClientStateParam = true;
    780             break;
    781             }
    782         case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
    783             int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
    784             *out = buffer;
    785             isClientStateParam = true;
    786             break;
    787             }
    788         case GL_MAX_VERTEX_ATTRIBS: {
    789             if (m_maxVertexAttribsDirty) {
    790                 isClientStateParam = false;
    791             } else {
    792                 *out = m_maxVertexAttribs;
    793                 isClientStateParam = true;
    794             }
    795             break;
    796         }
    797         }
    798         return isClientStateParam;
    799     }
    800 
    801 };
    802 #endif
    803